docker-compose.yml
Rama main · réplica de lectura del repositorio original.
# Self-hosted Aglyn (AGL-905): the console (management UI) and the tenant
# runtime (serves published sites) as two containers.
#
# cp .env.selfhost.example .env.selfhost # fill it in — see docs/SELF_HOSTING.md
# docker compose up --build
#
# The env file is used twice: as a BuildKit secret during the image build
# (Next.js inlines NEXT_PUBLIC_* into the client bundles) and as runtime env
# for the server-side secrets. Rebuild the images whenever a NEXT_PUBLIC_*
# value changes — runtime env alone cannot update the client bundle.
#
# In front of these, run your own reverse proxy (Caddy/nginx/Traefik):
# console on one hostname, tenant on a wildcard domain for your sites.
services:
console:
build:
context: .
dockerfile: docker/console.Dockerfile
args:
# Stamps the build so /api/health can say which one it is (AGL-2091).
# Optional — empty means the health body reports `commit: null` rather
# than a made-up id, and `version` answers regardless.
# COMMIT_REF=$(git rev-parse HEAD) docker compose up --build
COMMIT_REF: ${COMMIT_REF:-}
secrets:
- selfhost_env
env_file: .env.selfhost
# Published on LOOPBACK, so the only way in is the reverse proxy the
# runbook puts in front (docs/SELF_HOSTING.md §5 proxies to
# `localhost:4200` / `localhost:4500`, i.e. this same host).
#
# A bare `4200:4200` binds every interface, so the container also answers
# requests that never passed through the proxy — and those carry whatever
# `x-forwarded-for` the caller typed. Every rate limiter in the product
# keys on the first hop of that header, so a directly reachable container
# hands an attacker a fresh bucket per request on passkey sign-in,
# password reset, org creation and form submission. Nothing errors; the
# limits simply stop counting.
#
# If your proxy runs on another host or in another Docker network, do NOT
# widen this — put the proxy on this host's network, or add a
# `docker-compose.override.yml` and make sure the port you expose is
# firewalled to the proxy alone.
ports:
- '127.0.0.1:4200:4200'
restart: unless-stopped
tenant:
build:
context: .
dockerfile: docker/tenant.Dockerfile
args:
COMMIT_REF: ${COMMIT_REF:-}
secrets:
- selfhost_env
env_file: .env.selfhost
# Published on LOOPBACK, so the only way in is the reverse proxy the
# runbook puts in front (docs/SELF_HOSTING.md §5 proxies to
# `localhost:4200` / `localhost:4500`, i.e. this same host).
#
# A bare `4200:4200` binds every interface, so the container also answers
# requests that never passed through the proxy — and those carry whatever
# `x-forwarded-for` the caller typed. Every rate limiter in the product
# keys on the first hop of that header, so a directly reachable container
# hands an attacker a fresh bucket per request on passkey sign-in,
# password reset, org creation and form submission. Nothing errors; the
# limits simply stop counting.
#
# If your proxy runs on another host or in another Docker network, do NOT
# widen this — put the proxy on this host's network, or add a
# `docker-compose.override.yml` and make sure the port you expose is
# firewalled to the proxy alone.
ports:
- '127.0.0.1:4500:4500'
restart: unless-stopped
secrets:
selfhost_env:
file: .env.selfhost