-
Notifications
You must be signed in to change notification settings - Fork 0
Deployment
Agora ships a root docker-compose.yml that builds and wires the whole stack with a two-axis profile
model, so a bare docker compose up starts nothing β you compose the deploy you want.
π Start with
docs/CHEAT-SHEET.mdβ it maps every deployment recipe to the env vars it needs and where to obtain each value.
Axis 1 β data plane + API (required, pick exactly one):
-
--profile supabaseβ external Supabase Postgres + Storage. -
--profile selfhostβ local Postgres + MinIO, fully self-contained.β οΈ The "local Postgres" here is thesupabase/postgresimage (the Supabase Postgres distribution), not a vanilla Postgres β Agora's migrations require its bundled extensions (pgvector, PostGIS, pgmq, pgcrypto) and theanon/authenticated/service_roleroles +auth.uid(). Self-hosting drops the Supabase cloud (hosted DB / Auth / Storage), not the Supabase Postgres image.
Either one brings up the API itself: agora (:4000), the Caddy front-door proxy, and cron.
Axis 2 β optional add-ons (compose freely on top):
-
--profile scorerβ moderation + social-graph subsystem (scorer Γ3 + Neo4j). -
--profile secure-chatβ the E2E delivery process + Redis. -
--profile scaleβ Redis as the cross-replica rate-limit store. -
--profile fullβ every functional add-on at once (scorer + secure-chat). -
--profile observabilityβ the bundled Grafana Alloy β Tempo/Mimir/Loki/Grafana stack (see below). -
--profile demoβ pulls theagora-demoSDK harness and serves it behind the front door at/demo/, auto-wired to the local API (a one-command evaluator).
docker compose --profile supabase up --build # just the API, Supabase-backed
docker compose --profile selfhost up --build # just the API, self-contained
docker compose --profile full --profile supabase up # everything, Supabase-backed
docker compose --profile secure-chat up --build # standalone secure-chat (remote DATABASE_URL, no API)
docker compose --profile selfhost --profile demo up # API + the SDK demo harness at /demo/Agora ships one complete env template per compose file β copy the one that matches how you run it:
| Template | Compose file | Data plane |
|---|---|---|
.env.dev.example |
docker-compose.dev.yml |
host-run app (dev) |
.env.selfhost.example |
docker-compose.yml |
container from source (local Postgres + MinIO) |
.env.prod.example |
docker-compose.prod.yml |
pulled production image |
Each defaults to a local Postgres + MinIO, with cloud Supabase as a commented in-file switch. Pick
one and cp it to .env. The docker-compose.prod.yml service definitions no longer use
env_file β every consumed var is enumerated explicitly (${VAR:?required} / ${VAR:-default}), so
no secret has to live in a .env on disk for a prod deploy (values come from the process environment:
shell export / systemd / Swarm / K8s secret injection). Full var-by-var reference:
docs/CHEAT-SHEET.md.
A few deploy-significant knobs beyond the data plane:
-
CONTENT_DELETE_MODE(defaulthard) β out of the box, deleting an entity / comment / chat message / event trulyDELETEs the row (FK cascades take dependents) and removes its uploaded media from storage. SetCONTENT_DELETE_MODE=softto keep the previous recoverable-tombstone behavior (media stays in the bucket). See Security. -
Native-auth email β when
DEFAULT_AUTH_PROVIDER=native, the confirm/reset/resend flows requireAUTH_EMAIL_LINK_ALLOWED_ORIGINS(an allowlist of client origins the emailed link may point at) or they fail closed with503 auth/email-not-configured. A client'semailRedirectTois validated against it (open-redirect guard), so a multi-front-end deploy sends each user's link back to the site they signed up on. Native transactional email goes out over Postmark (POSTMARK_*); Supabase-backed auth brokers its own emails and is unaffected. -
Push notifications β set the
VAPID_PUBLIC_KEY/VAPID_PRIVATE_KEY/VAPID_SUBJECTtrio to enable Web Push dispatch (unset β push is a no-op); FCM/APNs providers are credential-gated. See API & Contract.
The proxy service is a Caddy front door β the single public entrypoint. It terminates TLS with
automatic Let's Encrypt certs (auto-renewed), serves the admin SPA (baked into its image), routes
every service, and adds HSTS + security headers, a body-size cap, and an authoritative
X-Forwarded-For. For a real domain set SERVER_NAME=your.domain (DNS β this host so ACME can
validate on :80) and RATE_LIMIT_TRUSTED_HOPS=1.
β οΈ ACME defaults to Let's Encrypt staging (untrusted certs, but safe against prod rate limits while you validate DNS/firewall). SetACME_CA=https://acme-v02.api.letsencrypt.org/directoryfor real, browser-trusted certs before going live.- Plain HTTP behind your own TLS terminator:
SERVER_NAME=:80. - Tor / bring-your-own-cert: the
Caddyfile.onionstatic-cert variant (viaCADDYFILE). - Custom routing / extra site blocks, and overriding the baked config via bind mounts:
deploy/proxy/README.md.
The selfhost data plane runs the same server fully self-contained via provider seams β native
email/password auth (DEFAULT_AUTH_PROVIDER=native) + S3-compatible storage (STORAGE_PROVIDER=s3
β MinIO/AWS) + a local Postgres. "No Supabase" means no Supabase cloud β the local DB is still the
supabase/postgres distribution (required for pgvector/PostGIS/pgmq + the auth roles; a vanilla
Postgres won't migrate). See
docs/SELF-HOSTING.md.
-
Redis (optional) β the suspension index and a shared rate-limit store; required for some add-ons.
docs/REDIS.md. -
Neo4j / DozerDB (optional) β backs the Social Graph; setup, plugins, memory tuning, TLS:
docs/DOZERDB.md.
Every service (the API, secure-chat, and the Python scorer) is OpenTelemetry-instrumented β traces,
metrics, and logs with traceβlog correlation. Telemetry is off by default (bare deploys stay dark);
OTEL_SDK_DISABLED=false is the single on-switch. --profile observability brings up a bundled,
self-contained Grafana Alloy β Tempo / Mimir / Loki / Grafana stack with the apps' exporters
pre-wired and two Agora dashboards (Overview + Logs) auto-provisioned, or you can point the OTLP/scrape
endpoints at your own collector. Full guide:
docs/TELEMETRY.md.
A docker-compose.prod.yml pulls pre-built multi-arch images (GHCR + Docker Hub) instead of building
locally. Images are published on version tags by the docker-publish workflow. Release/versioning
process: docs/RELEASE.md.
Agora Β· AGPL-3.0-only Β· the community edition is AGPL-3.0 forever.
These pages are published from wiki/ in the main repo β edit there via PR, not in the wiki directly.