QWED Deployment Guide
This guide provides instructions for deploying QWED in various environments.
Table of Contents
- Docker Deployment
- Kubernetes Deployment
- Manual / Bare Metal Deployment
- Environment Variables Reference
- Production Checklist
- Troubleshooting
- Operations & Monitoring
Docker Deployment
The easiest way to run QWED locally or on a single server is using Docker Compose.
Dockerfile
A Dockerfile is provided in the root directory. It builds the QWED core service based on python:3.11-slim.
# Build the image manually
docker build -t qwed-core:2.0.0 .
Docker Compose
We provide a docker-compose.yml that orchestrates:
- qwed-core: The main API server.
- postgres: Primary database.
- redis: Cache and rate limiting.
- jaeger: Distributed tracing.
- prometheus: Metrics collection.
- grafana: Observability dashboards.
To start the stack:
docker-compose up -d
Access the services:
- API: http://localhost:8000
- API Docs: http://localhost:8000/docs
- Grafana: http://localhost:3000 (admin/qwed_admin)
- Jaeger: http://localhost:16686
🏢 Enterprise Support Coming Soon: Managed hosting, dedicated support, and SLA guarantees. Contact rahul@qwedai.com
Notes on Stats Verification
The Stats Verification engine (Engine 3) executes code securely inside Docker containers. For this to work in a Docker Compose environment, the qwed-core container mounts the host's Docker socket (/var/run/docker.sock). Ensure the user running Docker Compose has appropriate permissions.
Kubernetes Deployment
For production environments, we provide Kubernetes manifests in deploy/kubernetes/.
Prerequisites
- A running Kubernetes cluster (v1.24+ recommended).
kubectlconfigured.- A PostgreSQL database and Redis instance (managed services recommended for production).
Deployment Steps
-
Create Namespace
kubectl create namespace qwed -
Configure Secrets & ConfigMaps Edit
deploy/kubernetes/secret.yamlwith your real API keys and database credentials.kubectl apply -f deploy/kubernetes/configmap.yaml
kubectl apply -f deploy/kubernetes/secret.yaml -
Deploy Application
kubectl apply -f deploy/kubernetes/deployment.yaml
kubectl apply -f deploy/kubernetes/service.yaml -
Verify Deployment
kubectl get pods -n qwed
Horizontal Pod Autoscaling (HPA)
For high-traffic environments, we recommend enabling HPA (requires Metrics Server):
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: qwed-core-hpa
namespace: qwed
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: qwed-core
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Manual / Bare Metal Deployment
If you prefer to run the application directly on a host or VM:
1. Prerequisites
Docker Installation (Required for Secure Code Execution) QWED uses Docker for secure code execution in the Stats Verification engine.
Linux (Ubuntu/Debian)
sudo apt-get update
sudo apt-get install docker.io
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker $USER
2. Python Dependencies
# Install dependencies
pip install -e .
3. Database Setup
Ensure PostgreSQL and Redis are running. Set the DATABASE_URL and REDIS_URL environment variables.
Initialize the database:
python -c "from qwed_new.core.database import create_db_and_tables; create_db_and_tables()"
4. Running the API
# Production Mode with Gunicorn (Linux/macOS)
gunicorn qwed_new.api.main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
Environment Variables Reference
Infrastructure
| Variable | Description | Default | Required |
|---|---|---|---|
DATABASE_URL | Postgres connection string | sqlite:///./qwed.db | Yes (Prod) |
REDIS_URL | Redis connection string | redis://localhost:6379/0 | Yes (Prod) |
API_KEY_SECRET | Secret key for signing JWTs | change-me... | YES |
Security Configuration
| Variable | Description | Default |
|---|---|---|
MAX_INPUT_LENGTH | Max query length (chars) | 2000 |
SIMILARITY_THRESHOLD | Prompt injection detection threshold | 0.6 |
DOCKER_TIMEOUT | Code execution timeout (seconds) | 10 |
DOCKER_MEMORY_LIMIT | Container memory limit | 512m |
AI Providers
| Variable | Description | Default |
|---|---|---|
ACTIVE_PROVIDER | Selected LLM provider | azure_openai |
AZURE_OPENAI_API_KEY | API Key for Azure OpenAI | - |
AZURE_OPENAI_ENDPOINT | Endpoint URL | - |
ANTHROPIC_API_KEY | API Key for Anthropic | - |
Observability
| Variable | Description | Default |
|---|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT | Jaeger/OTLP Endpoint | http://localhost:4317 |
Production Checklist
Before going to production, ensure the following:
1. Database Setup
- Use a managed PostgreSQL instance (e.g., AWS RDS, Azure Database for PostgreSQL).
- Enable automated backups.
- Run database migrations.
2. Redis Configuration
- Use a managed Redis instance (e.g., AWS ElastiCache).
- Configure eviction policy (LRU).
- Enable persistence (RDB/AOF).
3. Security
- Rotate Keys: Change all default passwords and secrets.
- SSL/TLS: Ensure the API is behind a Load Balancer with a valid SSL certificate.
- Network Policies: Restrict access to database/Redis.
- Docker Security: Ensure the Docker socket is protected or use a secure container runtime (gVisor) for the Stats Verification engine if possible.
4. Observability
- Configure alert rules in Prometheus/Grafana.
- Ensure logs are shipped to a centralized logging system.
Troubleshooting
1. Docker Permission Denied
Error: docker: Got permission denied while trying to connect to the Docker daemon socket
Solution: Ensure the user running the app is in the docker group, or (for Docker Compose) ensure the socket is mounted correctly and the container user has permissions.
2. Stats Verification Failing
Error: SecureCodeExecutor initialization failed
Solution:
- Check Docker is running:
docker ps - Check
python:3.10-slimimage exists:docker pull python:3.10-slim(The executor uses this image).
Operations & Monitoring
View Recent Security Events
# Python script
python -c "
from qwed_new.core.database import get_session
from qwed_new.core.models import SecurityEvent
from sqlmodel import select
with get_session() as session:
events = session.exec(
select(SecurityEvent)
.where(SecurityEvent.event_type == 'BLOCKED')
.order_by(SecurityEvent.timestamp.desc())
.limit(10)
).all()
for e in events:
print(f'{e.timestamp}: {e.reason}')
"
Security Metrics Dashboard
# Block rate by hour
sqlite3 qwed_v2.db "
SELECT strftime('%Y-%m-%d %H:00', timestamp) as hour, COUNT(*) as blocks
FROM security_event
WHERE event_type = 'BLOCKED'
GROUP BY hour
ORDER BY hour DESC
LIMIT 24;
"
For detailed architecture documentation, see: