Production with Compose
Use the production overlay for a public instance with TLS, private service ports, and a persistent worker.
Prepare the host and domains
Use a current Docker Compose plugin that supports !reset (2.24.4 or newer). Point DOMAIN, files.DOMAIN, and home.DOMAIN at the server. The supplied Caddy configuration sends the product to app:3000, /api/inngest to worker:8020, files to SeaweedFS, and the public site to landing:3001.
DOMAIN=workspace.example.com
ACME_EMAIL=ops@example.com
BETTER_AUTH_URL=https://workspace.example.com
APP_PUBLIC_URL=https://workspace.example.com
OCR_DEFAULT_PROVIDER=AZURE
AZURE_DOC_INTELLIGENCE_ENDPOINT=https://your-resource.cognitiveservices.azure.com
AZURE_DOC_INTELLIGENCE_KEY=replace-with-your-resource-key
CONVERTER_ALLOWED_FETCH_ORIGINS=https://workspace.example.com,https://files.workspace.example.com
ADEU_ALLOWED_FETCH_ORIGINS=https://workspace.example.com,https://files.workspace.example.comReplace the local defaults for database, storage, auth, file tokens, and all service credentials. Keep EMBEDDING_SECRETS_KEY stable: it protects stored provider credentials and OAuth grants.
Forward settings to both processes
Compose uses an explicit environment allowlist. A value in .env reaches a container only if that service forwards it. Add an operator override for settings absent from the base file, including APP_PUBLIC_URL and any OAuth or feature flags you enable.
services:
app:
environment: &operator-env
APP_PUBLIC_URL: ${APP_PUBLIC_URL:?Set the public app origin}
worker:
environment: *operator-envAdd provider client IDs, secrets, and feature flags to this shared block when enabling connections or optional capabilities. Existing base values are retained by the Compose merge.
Build the public site for your origins
NEXT_PUBLIC_* variables are bundled at build time. The current landing Dockerfile does not consume build arguments for its origins; runtime environment entries in the production overlay cannot rewrite account links already in the browser bundle. Add the following to its builder stage before the build command, then pass matching build.args on the landing service.
ARG NEXT_PUBLIC_SITE_URL
ARG NEXT_PUBLIC_APP_URL
ENV NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL
ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URLSet landing build arguments
Extend the same operator override with the landing service below. Use the same origins for the build and runtime settings.
landing:
build:
args:
NEXT_PUBLIC_SITE_URL: https://home.${DOMAIN}
NEXT_PUBLIC_APP_URL: https://${DOMAIN}Start and check the merged stack
The overlay uses published app and worker images; migrations still build from your checkout. For repeatable releases, pin both images to a tested release or digest and use a matching source checkout for migrations and model configuration. Preview the merged service names, then start.
docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.operator.yml --env-file .env config --services
docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.operator.yml --env-file .env up --build -d
docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.operator.yml logs --tail=100 migrate app worker caddyThe lean overlay disables local Whisper and the Inngest dev server. Configure cloud transcription and OCR, or explicitly enable the relevant profiles. The supplied files hostname serves objects anonymously by URL; choose storage and access controls that fit your deployment.