This guide covers deploying BotForge RAG in various environments, from development to production-grade deployments.
- BotForge API: Main FastAPI application
- PostgreSQL: Primary database for bots, MCP servers, and logs
- Redis: Cache for embeddings and session data
- Vector Model: SentenceTransformers embedding model
- OpenAI API: For LLM responses
- External MCP Servers: Custom tool servers
Create docker-compose.yml:
version: '3.8'
services:
postgres:
image: postgres:15
environment:
POSTGRES_DB: botforge
POSTGRES_USER: botforge
POSTGRES_PASSWORD: botforge123
volumes:
- postgres_data:/var/lib/postgresql/data
- ./create.sql:/docker-entrypoint-initdb.d/create.sql
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U botforge"]
interval: 30s
timeout: 10s
retries: 3
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
botforge-api:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql+asyncpg://botforge:botforge123@postgres:5432/botforge
- REDIS_URL=redis://redis:6379
- OPENAI_API_KEY=${OPENAI_API_KEY}
- VECTOR_MODEL_PATH=all-MiniLM-L6-v2
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./models:/app/models
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
volumes:
postgres_data:
redis_data:Create Dockerfile:
FROM python:3.9-slim
# Set working directory
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY src/ ./src/
COPY config/ ./config/
# Create models directory for vector model cache
RUN mkdir -p models
# Set Python path
ENV PYTHONPATH=/app/src
# Expose port
EXPOSE 8000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# Run the application
CMD ["python", "-m", "botforge.main"]Create .env file:
# Database
DATABASE_URL=postgresql+asyncpg://botforge:botforge123@localhost:5432/botforge
# Redis
REDIS_URL=redis://localhost:6379
# OpenAI
OPENAI_API_KEY=sk-your-openai-api-key-here
# Vector Model
VECTOR_MODEL_PATH=all-MiniLM-L6-v2
# Server Configuration
HOST=0.0.0.0
PORT=8000
DEBUG=false
LOG_LEVEL=INFO
# Performance Tuning
MAX_CHUNKS=5
SIMILARITY_THRESHOLD=0.7
MCP_TIMEOUT_SECONDS=30
MCP_RETRY_ATTEMPTS=3
# Security
ALLOWED_ORIGINS=http://localhost:3000,https://yourdomain.com
RATE_LIMIT_PER_MINUTE=100# Build and start services
docker-compose up -d
# Check logs
docker-compose logs -f botforge-api
# Run database migrations
docker-compose exec botforge-api python -m alembic upgrade head
# Scale API instances
docker-compose up -d --scale botforge-api=3
# Stop services
docker-compose downk8s/namespace.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: botforge
labels:
name: botforgek8s/configmap.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: botforge-config
namespace: botforge
data:
HOST: "0.0.0.0"
PORT: "8000"
LOG_LEVEL: "INFO"
VECTOR_MODEL_PATH: "all-MiniLM-L6-v2"
MAX_CHUNKS: "5"
SIMILARITY_THRESHOLD: "0.7"
MCP_TIMEOUT_SECONDS: "30"
MCP_RETRY_ATTEMPTS: "3"k8s/secrets.yaml:
apiVersion: v1
kind: Secret
metadata:
name: botforge-secrets
namespace: botforge
type: Opaque
data:
DATABASE_URL: <base64-encoded-database-url>
REDIS_URL: <base64-encoded-redis-url>
OPENAI_API_KEY: <base64-encoded-openai-key>k8s/postgres.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: botforge
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
env:
- name: POSTGRES_DB
value: botforge
- name: POSTGRES_USER
value: botforge
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
- name: init-sql
mountPath: /docker-entrypoint-initdb.d
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
- name: init-sql
configMap:
name: postgres-init
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
namespace: botforge
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432k8s/redis.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: botforge
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
volumeMounts:
- name: redis-storage
mountPath: /data
volumes:
- name: redis-storage
persistentVolumeClaim:
claimName: redis-pvc
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: botforge
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379k8s/botforge-api.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: botforge-api
namespace: botforge
spec:
replicas: 3
selector:
matchLabels:
app: botforge-api
template:
metadata:
labels:
app: botforge-api
spec:
containers:
- name: botforge-api
image: botforge/botforge-rag:latest
ports:
- containerPort: 8000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: botforge-secrets
key: DATABASE_URL
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: botforge-secrets
key: REDIS_URL
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: botforge-secrets
key: OPENAI_API_KEY
envFrom:
- configMapRef:
name: botforge-config
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: botforge-api-service
namespace: botforge
spec:
selector:
app: botforge-api
ports:
- port: 80
targetPort: 8000
type: ClusterIPk8s/ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: botforge-ingress
namespace: botforge
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rate-limit: "100"
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
spec:
tls:
- hosts:
- api.botforge.com
secretName: botforge-tls
rules:
- host: api.botforge.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: botforge-api-service
port:
number: 80# Create namespace
kubectl apply -f k8s/namespace.yaml
# Apply configurations
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secrets.yaml
# Deploy services
kubectl apply -f k8s/postgres.yaml
kubectl apply -f k8s/redis.yaml
kubectl apply -f k8s/botforge-api.yaml
kubectl apply -f k8s/ingress.yaml
# Check status
kubectl get pods -n botforge
kubectl get services -n botforge
# View logs
kubectl logs -f deployment/botforge-api -n botforge
# Scale deployment
kubectl scale deployment botforge-api --replicas=5 -n botforge- CPU: 2 vCPU
- Memory: 4 GB RAM
- Storage: 20 GB SSD
- Network: 1 Gbps
- CPU: 4+ vCPU
- Memory: 8+ GB RAM
- Storage: 100+ GB SSD
- Network: 10 Gbps
- Load Balancer: Yes
- Auto-scaling: Yes
postgresql.conf:
# Connection Settings
max_connections = 200
shared_buffers = 256MB
effective_cache_size = 1GB
maintenance_work_mem = 64MB
# Write-Ahead Logging
wal_buffers = 16MB
checkpoint_completion_target = 0.9
wal_writer_delay = 200ms
# Query Tuning
random_page_cost = 1.1
effective_io_concurrency = 200
# Logging
log_destination = 'stderr'
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_min_duration_statement = 1000redis.conf:
# Memory Management
maxmemory 2gb
maxmemory-policy allkeys-lru
# Persistence
save 900 1
save 300 10
save 60 10000
# Security
requirepass your-redis-password
rename-command FLUSHDB ""
rename-command FLUSHALL ""
# Performance
tcp-keepalive 300
timeout 0nginx.conf:
upstream botforge_api {
least_conn;
server 10.0.1.10:8000 max_fails=3 fail_timeout=30s;
server 10.0.1.11:8000 max_fails=3 fail_timeout=30s;
server 10.0.1.12:8000 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name api.botforge.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name api.botforge.com;
ssl_certificate /etc/ssl/certs/botforge.crt;
ssl_certificate_key /etc/ssl/private/botforge.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req zone=api burst=20 nodelay;
# Compression
gzip on;
gzip_types application/json text/plain application/javascript;
location / {
proxy_pass http://botforge_api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Health checks
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
}
location /health {
proxy_pass http://botforge_api;
access_log off;
}
}prometheus.yml:
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'botforge-api'
static_configs:
- targets: ['localhost:8000']
metrics_path: /metrics
scrape_interval: 15s
- job_name: 'postgres'
static_configs:
- targets: ['localhost:9187']
- job_name: 'redis'
static_configs:
- targets: ['localhost:9121']Key metrics to monitor:
- Query Response Times: P50, P95, P99
- Intent Detection Accuracy: Success rate
- MCP Tool Execution: Success rate, latency
- Database Performance: Connection pool, query time
- Cache Hit Rates: Redis performance
- Error Rates: 4xx, 5xx responses
# Use strong passwords
export POSTGRES_PASSWORD=$(openssl rand -base64 32)
export REDIS_PASSWORD=$(openssl rand -base64 32)
# Restrict database access
export DATABASE_URL="postgresql+asyncpg://botforge:${POSTGRES_PASSWORD}@db-host:5432/botforge?sslmode=require"
# Use secure Redis
export REDIS_URL="redis://:${REDIS_PASSWORD}@redis-host:6379/0"
# Secure OpenAI key
export OPENAI_API_KEY="sk-your-secure-key"# Firewall rules (example for iptables)
iptables -A INPUT -p tcp --dport 8000 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 5432 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -j DROP#!/bin/bash
# backup-db.sh
BACKUP_DIR="/backups/postgres"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="botforge_backup_${DATE}.sql"
# Create backup
pg_dump -h localhost -U botforge -d botforge > "${BACKUP_DIR}/${BACKUP_FILE}"
# Compress backup
gzip "${BACKUP_DIR}/${BACKUP_FILE}"
# Upload to S3 (optional)
aws s3 cp "${BACKUP_DIR}/${BACKUP_FILE}.gz" s3://botforge-backups/
# Clean old backups (keep last 7 days)
find ${BACKUP_DIR} -name "*.gz" -mtime +7 -delete#!/bin/bash
# backup-redis.sh
BACKUP_DIR="/backups/redis"
DATE=$(date +%Y%m%d_%H%M%S)
# Create Redis backup
redis-cli --rdb "${BACKUP_DIR}/dump_${DATE}.rdb"
# Upload to S3
aws s3 cp "${BACKUP_DIR}/dump_${DATE}.rdb" s3://botforge-backups/redis/k8s/hpa.yaml:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: botforge-api-hpa
namespace: botforge
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: botforge-api
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80# src/botforge/core/config.py
class ProductionSettings(Settings):
# Connection pooling
database_pool_size: int = 20
database_max_overflow: int = 30
# Redis connection pool
redis_pool_size: int = 50
redis_pool_timeout: int = 30
# Performance tuning
max_concurrent_requests: int = 100
request_timeout: int = 30
# Caching
cache_ttl: int = 3600
embedding_cache_size: int = 10000# Pre-load and warm up models
async def startup_event():
# Warm up vector model
vector_model = SentenceTransformer('all-MiniLM-L6-v2')
vector_model.encode("warmup text")
# Pre-compile common queries
await redis_client.set("model:ready", "true")- Environment variables configured
- Database migrations applied
- SSL certificates installed
- Monitoring configured
- Backup procedures tested
- Load testing completed
- Health checks passing
- Metrics collection working
- Error tracking enabled
- Log aggregation configured
- Alert rules configured
- Documentation updated
High Memory Usage:
# Check vector model memory
ps aux | grep python
# Optimize model loading
export SENTENCE_TRANSFORMERS_HOME=/tmp/modelsDatabase Connection Issues:
# Check connection pool
SELECT count(*) FROM pg_stat_activity;
# Increase pool size
export DATABASE_POOL_SIZE=30Redis Connection Issues:
# Check Redis connections
redis-cli info clients
# Increase connection pool
export REDIS_POOL_SIZE=100# Check API health
curl -f https://api.botforge.com/health
# Monitor database performance
kubectl exec -it postgres-pod -- psql -U botforge -c "SELECT * FROM pg_stat_activity;"
# Check API logs
kubectl logs -f deployment/botforge-api -n botforge
# Monitor resource usage
kubectl top pods -n botforgeThis deployment guide provides comprehensive instructions for deploying BotForge RAG in production environments with proper security, monitoring, and scalability considerations.