Deployment
Self-hosted deployment options for Quox.
QuoxCORE is designed for self-hosted deployment, giving you full control over your data and infrastructure. All services build from source using Docker Compose.
System Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 4 cores | 8 cores |
| RAM | 8 GB | 16 GB |
| Disk | 40 GB SSD | 100 GB SSD |
| OS | Linux (x86_64) | Ubuntu 22.04+ / Debian 12+ |
| Docker | Docker Engine 24+ with Compose v2 | Latest stable |
| Node.js | 18+ (build only) | 20 LTS |
QuoxCORE runs approximately 12 services. Qdrant (vector DB) and PostgreSQL are the most memory-hungry.
Docker Compose Deployment
1. Clone and configure
git clone [email protected]:quoxai/quox.git quox-dashboard
cd quox-dashboard
# Copy the example environment file
cp .env.example .env
# Auto-generate secrets (JWT, encryption keys, Qdrant API key, etc.)
./scripts/generate-secrets.sh
Edit .env and fill in any API keys you need:
# ============================================
# REQUIRED - Generated by generate-secrets.sh
# ============================================
JWT_SECRET=<generated>
MASTER_ENCRYPTION_KEY=<generated>
QDRANT_API_KEY=<generated>
POSTGRES_PASSWORD=<generated>
INTERNAL_SERVICE_KEY=<generated>
# ============================================
# REQUIRED - Docker host config
# Auto-detected by generate-secrets.sh
# ============================================
# DOCKER_GID=988
# ============================================
# OPTIONAL - API Keys (add for full AI functionality)
# ============================================
ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxx
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx
ELEVENLABS_API_KEY=
# ============================================
# OPTIONAL - SMTP (for user invitations / password resets)
# ============================================
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
[email protected]
# ============================================
# OPTIONAL - SSL
# ============================================
SSL_MODE=selfsigned
# LETSENCRYPT_DOMAIN=quox.yourdomain.com
# [email protected]
# ============================================
# PORTS (defaults shown)
# ============================================
DASHBOARD_PORT=3000
AUTH_PORT=3101
FILES_PORT=3102
COLLECTOR_PORT=9848
QDRANT_PORT=6333
POSTGRES_PORT=5432
2. Generate SSL certificates
The dashboard serves over HTTPS. Generate a self-signed certificate for local/dev use:
./scripts/generate-certs.sh
cp certs/cert.pem ssl/quox.crt
cp certs/key.pem ssl/quox.key
For production with Let's Encrypt, set SSL_MODE=letsencrypt in .env and use ./scripts/ssl-manager.sh init.
3. Clone QuoxMCP (required for AI tool execution)
The collector service mounts QuoxMCP for MCP protocol tool execution. Without it, AI agents will have no tool capability.
git clone [email protected]:quoxai/quoxmcp.git /home/control/quoxmcp
4. Start services
# Start all core services
docker compose up -d
# Optionally include n8n (legacy workflow engine, 400+ third-party connectors)
docker compose --profile with-n8n up -d
# Verify everything is healthy
docker compose ps
5. Complete setup
Open https://localhost:3000 in your browser and complete the Setup Wizard.
Service overview
QuoxCORE runs the following services (all build from source except Qdrant and PostgreSQL):
| Service | Port | Description |
|---|---|---|
| dashboard | 3000 (HTTPS) | React frontend served by nginx |
| auth | 3101 | Authentication, RBAC, JWT tokens |
| files | 3102 | File storage service |
| memory | 3103 | Server-side memory persistence (SQLite + FTS5) |
| tasks | 3104 | Background task scheduler |
| collector | 9848 | Chat streaming, fleet management, AI tool execution |
| orchestrator | 3100 | Container orchestration via Docker socket |
| quoxflow | 3200 | Auditable workflow engine (TypeScript) |
| qdrant | 6333 | Vector database for semantic search |
| postgres | 5432 | PostgreSQL database for QuoxFlow |
| n8n | 5678 | Workflow automation (optional, behind with-n8n profile) |
| screencap | 3300 | Headless browser screenshots (optional, behind with-screencap profile) |
All internal services bind to 127.0.0.1 only. The collector (9848) is exposed on all interfaces because remote QuoxAgent instances send heartbeats to it.
Reverse Proxy Setup
If you place QuoxCORE behind an external reverse proxy, the dashboard already runs nginx internally. You only need to forward traffic to the dashboard port.
Nginx
server {
listen 443 ssl http2;
server_name quox.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/quox.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/quox.yourdomain.com/privkey.pem;
# Dashboard (handles all routing internally)
location / {
proxy_pass https://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}
Traefik
# docker-compose.override.yml
services:
dashboard:
labels:
- "traefik.enable=true"
- "traefik.http.routers.quox.rule=Host(`quox.yourdomain.com`)"
- "traefik.http.routers.quox.tls.certresolver=letsencrypt"
- "traefik.http.services.quox.loadbalancer.server.scheme=https"
- "traefik.http.services.quox.loadbalancer.server.port=443"
Production Checklist
Security
- TLS certificates -- Use Let's Encrypt or your own CA, not self-signed
- Secrets generated -- All keys in
.envare unique random values (rungenerate-secrets.sh) -
.envnot in version control -- Confirm.gitignoreincludes.env - Cookie security -- Set
COOKIE_SECURE=truefor HTTPS deployments - Firewall rules -- Only expose required ports
# External ports (must be reachable)
3000/tcp # Dashboard (HTTPS, behind reverse proxy)
9848/tcp # Collector (QuoxAgent heartbeats from remote hosts)
# Internal only (bind to 127.0.0.1 by default)
3100/tcp # Orchestrator
3101/tcp # Auth
3102/tcp # Files
3103/tcp # Memory
3104/tcp # Tasks
5432/tcp # PostgreSQL
5678/tcp # n8n (if enabled)
6333/tcp # Qdrant
- RBAC configured -- Users have appropriate roles
- Audit logging enabled -- All actions logged via AEE protocol
Data Persistence
All service data is stored in named Docker volumes. Verify they are created:
docker volume ls | grep quox
Key volumes to back up:
| Volume | Contents |
|---|---|
quox-auth-data | User accounts, sessions, credentials (SQLite) |
quox-collector-data | AEE envelope database, chat history |
quox-memory-data | Learned memories (SQLite + FTS5) |
quox-qdrant-data | Vector embeddings |
quox-postgres-data | QuoxFlow workflow data |
quox-files-data | Uploaded files and metadata |
quox-tasks-data | Scheduled task database |
# Example backup script
#!/bin/bash
DATE=$(date +%Y%m%d)
BACKUP_DIR="./backups/$DATE"
mkdir -p "$BACKUP_DIR"
# Stop services for consistent backup
docker compose stop
# Back up each volume
for vol in quox-auth-data quox-collector-data quox-memory-data quox-qdrant-data quox-postgres-data quox-files-data quox-tasks-data; do
docker run --rm -v "$vol":/data -v "$(pwd)/$BACKUP_DIR":/backup alpine \
tar czf "/backup/$vol.tar.gz" -C /data .
done
# Restart services
docker compose up -d
echo "Backup complete: $BACKUP_DIR"
- Backup strategy tested -- Run a backup and verify you can restore
- Restore tested -- Practice restoring from backup to a fresh environment
Monitoring
- Health checks -- All services have built-in health checks (visible via
docker compose ps) - Log rotation -- Configure Docker log limits
# Add to docker-compose.override.yml for log rotation
services:
dashboard:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
- Alerting -- Monitor
docker compose psfor unhealthy containers - Disk usage -- Watch Qdrant and PostgreSQL volume growth
Performance
- Resource limits -- Set memory limits for heavy services
# docker-compose.override.yml
services:
qdrant:
mem_limit: 4G
postgres:
mem_limit: 1G
collector:
mem_limit: 2G
Scaling
Vertical Scaling
For larger fleets and more concurrent users, increase resources on the host machine. The collector service handles QuoxAgent heartbeats and AI chat streaming -- it benefits most from additional CPU and RAM.
QuoxAgent Fleet
The collector can handle hundreds of QuoxAgent instances reporting in. Each agent connects over HTTPS to port 9848. For geographically distributed fleets, consider deploying multiple QuoxCORE instances per region.
Upgrading
Standard Upgrade
QuoxCORE services build from source, so upgrading means pulling the latest code and rebuilding:
cd quox-dashboard
# Pull latest code
git pull
# Rebuild all services
docker compose build
# Restart with new images
docker compose up -d
# Verify health
docker compose ps
Rebuilding Individual Services
If you only changed one service (e.g., the collector):
docker compose build collector
docker compose up -d collector
Note: The dashboard bakes the React frontend into its Docker image during build. After any frontend code change, you must rebuild the dashboard image.
Database Migrations
SQLite-based services (auth, memory, collector, tasks) run migrations automatically on startup. PostgreSQL migrations for QuoxFlow also run on boot. No manual migration step is needed.
Troubleshooting
Container won't start
# Check logs for the failing service
docker compose logs auth
docker compose logs collector
# Common causes:
# - Missing required env vars (JWT_SECRET, QDRANT_API_KEY, POSTGRES_PASSWORD)
# - Port conflicts with other services on the host
# - DOCKER_GID mismatch (re-run generate-secrets.sh)
QuoxAgent can't connect
# On the agent host, check QuoxAgent status
quoxagent status
# Verify the collector is reachable from the agent host
curl -s http://<quoxcore-ip>:9848/health
# On the QuoxCORE host, check collector logs
docker compose logs collector | grep heartbeat
Services unhealthy
# See which services are unhealthy
docker compose ps
# Restart a specific service
docker compose restart auth
# Full restart of all services
docker compose down && docker compose up -d
Qdrant memory issues
# Check Qdrant resource usage
docker stats quox-qdrant
# If OOM, increase the memory limit
# In docker-compose.override.yml:
# qdrant:
# mem_limit: 4G
SSL certificate issues
# Regenerate self-signed certs
./scripts/generate-certs.sh
cp certs/cert.pem ssl/quox.crt
cp certs/key.pem ssl/quox.key
docker compose restart dashboard
Next Steps
- First Integration -- Connect to your fleet
- Safety -- Configure DEFCON levels
- Workflows -- Set up automation
- Architecture -- Deep dive into components