# Waggle Teams — Production Docker Compose # # Usage: # docker compose -f docker-compose.production.yml up -d # # Required environment variables (create .env file or pass via -e): # ANTHROPIC_API_KEY — Your Anthropic API key # CLERK_SECRET_KEY — Clerk authentication secret (team mode) # CLERK_PUBLISHABLE_KEY — Clerk publishable key # CLERK_WEBHOOK_SIGNING_SECRET — Clerk user-webhook signing secret # CORS_ORIGIN — Frontend origin(s), comma-separated, exact-match. # REQUIRED: the team server (index.ts) fails closed in # production if unset. e.g. https://app.example.com # WAGGLE_LICENSE_KEY — Waggle license key (optional for V1) # # Required production secrets: # POSTGRES_PASSWORD - Postgres password # MINIO_ROOT_USER - MinIO access key # MINIO_ROOT_PASSWORD - MinIO secret key # # Optional: # OPENAI_API_KEY — If using OpenAI models # WAGGLE_MAX_USERS — Max team members (default: unlimited) # # NOTE: Stripe billing runs in the SIDECAR server (render.yaml), not this team # server — its webhooks route is Clerk-only, so no STRIPE_* vars are needed here. services: waggle: build: context: . dockerfile: Dockerfile image: waggle/server:latest ports: - '3333:3333' environment: - DATABASE_URL=postgres://waggle:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/waggle - REDIS_URL=redis://redis:6379 - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - OPENAI_API_KEY=${OPENAI_API_KEY:-} - CLERK_SECRET_KEY=${CLERK_SECRET_KEY:-} - CLERK_PUBLISHABLE_KEY=${CLERK_PUBLISHABLE_KEY:-} - CLERK_WEBHOOK_SIGNING_SECRET=${CLERK_WEBHOOK_SIGNING_SECRET:?set CLERK_WEBHOOK_SIGNING_SECRET} - WAGGLE_LICENSE_KEY=${WAGGLE_LICENSE_KEY:-} - WAGGLE_MAX_USERS=${WAGGLE_MAX_USERS:-0} - WAGGLE_SKIP_LITELLM=1 # Container must accept traffic from outside the container; the sidecar # now defaults to loopback (desktop-safe), so cloud/server deploys opt in. - WAGGLE_HOST=0.0.0.0 - NODE_ENV=production # Team server (packages/server/src/index.ts — this Dockerfile's entrypoint) # fails closed if CORS_ORIGIN is unset under NODE_ENV=production (config.ts). # Set it to your deployed frontend origin(s), comma-separated, exact-match. - CORS_ORIGIN=${CORS_ORIGIN:?set CORS_ORIGIN to your frontend origin, e.g. https://app.example.com} - MINIO_ENDPOINT=minio:9000 - MINIO_ACCESS_KEY=${MINIO_ROOT_USER:?set MINIO_ROOT_USER} - MINIO_SECRET_KEY=${MINIO_ROOT_PASSWORD:?set MINIO_ROOT_PASSWORD} - MINIO_BUCKET=waggle-files volumes: - waggle-data:/data depends_on: postgres: condition: service_healthy redis: condition: service_healthy minio: condition: service_healthy restart: unless-stopped healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://localhost:3333/health'] interval: 30s timeout: 5s retries: 3 start_period: 15s worker: image: waggle/server:latest command: ['node', 'packages/worker/dist/index.js'] environment: - DATABASE_URL=postgres://waggle:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/waggle - REDIS_URL=redis://redis:6379 - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - OPENAI_API_KEY=${OPENAI_API_KEY:-} - WAGGLE_SKIP_LITELLM=1 - NODE_ENV=production depends_on: waggle: condition: service_healthy postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped postgres: image: postgres:16-alpine environment: POSTGRES_USER: waggle POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD} POSTGRES_DB: waggle volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U waggle'] interval: 10s timeout: 5s retries: 5 restart: unless-stopped redis: image: redis:7-alpine volumes: - redisdata:/data healthcheck: test: ['CMD', 'redis-cli', 'ping'] interval: 10s timeout: 5s retries: 5 restart: unless-stopped minio: image: minio/minio:latest command: server /data --console-address ":9001" ports: - '9000:9000' - '9001:9001' environment: - MINIO_ROOT_USER=${MINIO_ROOT_USER:?set MINIO_ROOT_USER} - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:?set MINIO_ROOT_PASSWORD} volumes: - minio-data:/data healthcheck: test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live'] interval: 10s timeout: 5s retries: 5 restart: unless-stopped volumes: waggle-data: pgdata: redisdata: minio-data: