Checklist
The go-live pass before a self-hosted instance takes real traffic
Run through this once before the stack is reachable by anyone else. It assumes a working Compose install from Installation. Three things separate a laptop trial from a real deployment:
- Replace the dev-only secret defaults, and bring the stack up with the production overlay so it refuses to boot until they’re set
- Switch the backend to production mode
- Move the compose-managed data stores to managed services
Replace the dev-only secrets
The stack boots with dev-only placeholders baked into docker-compose.yml, values like local-dev-only-not-for-production-replace-me, and futureagi for the database passwords. It runs fine with them, which is the point on a laptop and the danger in production.
What forces real secrets is the production overlay, deploy/docker-compose.production.yml. It re-binds each one with ${VAR:?}, so the stack won’t start until you’ve set them.
These values go in deploy/.env.production, not the root .env. Copy the shipped example and fill it in:
cp deploy/.env.production.example deploy/.env.production
Set, at minimum:
SECRET_KEYAGENTCC_INTERNAL_API_KEYAGENTCC_ADMIN_TOKENPG_PASSWORDMINIO_ROOT_PASSWORDRABBITMQ_USERandRABBITMQ_PASSWORDFRONTEND_URLandVITE_HOST_API
openssl rand -hex 32 # SECRET_KEY, AGENTCC_INTERNAL_API_KEY, AGENTCC_ADMIN_TOKEN
openssl rand -base64 24 # PG_PASSWORD, MINIO_ROOT_PASSWORD, RABBITMQ_PASSWORD
Then bring the stack up with both files:
docker compose --env-file deploy/.env.production \
-f docker-compose.yml -f deploy/docker-compose.production.yml up -d
Miss one and compose refuses to start, naming the variable it wanted. That’s the overlay doing its job, not a broken install.
Warning
PG_PASSWORD is baked into the Postgres volume on the first boot, so set it before your first docker compose up. MINIO_ROOT_PASSWORD is read from the environment on every boot, so that one you can change and restart. The full field list is in Environment variables.
Switch the backend to production mode
Set these runtime flags before going live:
| Variable | Go-live value | Why |
|---|---|---|
ENV_TYPE | prod | Defaults to development. Disables debug output and runs Django check --deploy |
GRANIAN_WORKERS | your CPU count | One worker per core, up from the default 1 |
FAST_STARTUP | leave unset | Already false. Setting it true skips migrations and DB checks at boot, which you never want here |
check --deploy warns and continues rather than refusing to start, so a failing deployment check won’t stop the container. Read the backend logs on your first prod boot instead of assuming a clean start means a clean report.
Move to managed data stores
Compose-managed Postgres, ClickHouse, Redis, and MinIO are fine for a trial. For production, point the stack at managed services. The catch: the backend reads these hosts from hardcoded values in the backend env block of docker-compose.yml (PG_HOST: postgres, CH_HOST: clickhouse, REDIS_URL: redis://redis:6379/0, S3_ENDPOINT_URL: http://minio:9000), not from .env. Setting them in .env does nothing. You edit the compose file.
| Replace | With | Edit in docker-compose.yml |
|---|---|---|
postgres | RDS, Aurora, or Cloud SQL | PG_HOST / PG_PORT to the managed endpoint |
clickhouse | ClickHouse Cloud | CH_HOST / CH_PORT and the credentials |
redis | ElastiCache or Upstash | REDIS_URL |
minio | AWS S3 | STORAGE_BACKEND: s3 and the S3 credentials |
Note
code-executor runs with privileged: true, so it can’t run on ECS Fargate or Cloud Run. Put it on an EC2 or GCE instance. The platform matrix is in Requirements.
Dive deeper
Questions & Discussion