Skip to content

Docker Deployment

Deploy Gremia Cloud (the orchestrator service) using Docker and Docker Compose.

Architecture

graph TB
    subgraph Docker Host
        N[Nginx Reverse Proxy]
        O[Orchestrator Container]
        R[Redis Container]
    end

    S[Supabase Cloud] --- O
    N -->|HTTPS + WSS| O
    O --> R
    I[Internet] -->|443| N

The orchestrator runs as a single FastAPI container behind an Nginx reverse proxy. Supabase (PostgreSQL) runs as a managed service in the EU region.

Prerequisites

Tool Version
Docker 24.0+
Docker Compose 2.20+
Domain name With DNS A record pointing to your server
SSL certificate Let's Encrypt or commercial (for Nginx)

Quick Start

1. Clone the repository

git clone https://github.com/JdPG23/gremia-labs.git
cd gremia-labs

2. Configure environment

Copy the example environment file and fill in your values:

cp infra/docker/.env.example infra/docker/.env

Required environment variables:

Variable Description
SUPABASE_URL Your Supabase project URL
SUPABASE_SERVICE_KEY Supabase service role key
JWT_SECRET Secret for JWT signing (min 32 chars)
ANTHROPIC_API_KEY Anthropic API key for AI models
ENCRYPTION_KEY AES-256 encryption key (hex, 64 chars)
STRIPE_SECRET_KEY Stripe secret key for billing
STRIPE_WEBHOOK_SECRET Stripe webhook signing secret
CA_CERT_PATH Path to CA certificate for mTLS
CA_KEY_PATH Path to CA private key for mTLS

Security

Never commit .env files to version control. Use a secrets manager (Vault, AWS Secrets Manager, etc.) in production.

3. Build and start

cd infra/docker
docker compose up -d --build

This starts:

  • orchestrator — FastAPI app on port 8000 (internal)
  • nginx — Reverse proxy on ports 80/443 (public)

4. Verify

curl https://your-domain.com/health
# Expected: {"status": "healthy", "version": "0.1.0"}

Docker Compose Configuration

# infra/docker/docker-compose.yml
services:
  orchestrator:
    build:
      context: ../../
      dockerfile: infra/docker/Dockerfile.orchestrator
    env_file: .env
    ports:
      - "8000:8000"
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - /etc/letsencrypt:/etc/letsencrypt:ro
    depends_on:
      - orchestrator
    restart: unless-stopped

Nginx Configuration

Key sections for the reverse proxy:

# WebSocket upgrade for tunnel
location /api/v1/tunnel/ws {
    proxy_pass http://orchestrator:8000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_read_timeout 86400;

    # mTLS client certificate (optional)
    proxy_set_header X-Client-Cert $ssl_client_cert;
}

# REST API
location /api/ {
    proxy_pass http://orchestrator:8000;
    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;
}

SSL with Let's Encrypt

# Install certbot
apt install certbot python3-certbot-nginx

# Generate certificate
certbot --nginx -d your-domain.com

# Auto-renewal (crontab)
0 0 * * * certbot renew --quiet

Monitoring

Health check

curl https://your-domain.com/health

Prometheus metrics

curl https://your-domain.com/metrics

Exposed metrics:

Metric Type Description
gremia_http_requests_total Counter Total HTTP requests by method, path, status
gremia_http_request_duration_seconds Histogram Request latency
gremia_ws_connections_active Gauge Active WebSocket connections
gremia_ws_connections_total Counter Total WebSocket connections
gremia_executions_total Counter Total task executions by status

Logs

# Follow orchestrator logs
docker compose logs -f orchestrator

# Last 100 lines
docker compose logs --tail=100 orchestrator

Scaling

Horizontal scaling

The orchestrator is stateless (state lives in Supabase). Run multiple instances behind a load balancer:

services:
  orchestrator:
    deploy:
      replicas: 3

WebSocket affinity

WebSocket connections require sticky sessions. Configure your load balancer to use source IP affinity for the /api/v1/tunnel/ws path.

Resource limits

services:
  orchestrator:
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: 2G
        reservations:
          cpus: "0.5"
          memory: 512M

Backup and Recovery

Database

Supabase provides automated daily backups. For manual backups:

pg_dump $DATABASE_URL > backup_$(date +%Y%m%d).sql

Encryption keys

Store encryption keys in a secure vault. If the key is lost, encrypted data cannot be recovered. Use the key rotation API to rotate keys periodically.

Updating

cd gremia-labs
git pull origin main
cd infra/docker
docker compose build orchestrator
docker compose up -d orchestrator

The orchestrator supports zero-downtime updates when running multiple replicas behind a load balancer.