diff --git a/docker-compose.yml b/docker-compose.yml index 6611cd9..a757656 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -146,12 +146,21 @@ services: cloudflared: image: cloudflare/cloudflared:2026.6.0 restart: unless-stopped + # The token arrives via TUNNEL_TOKEN (which cloudflared reads natively) + # rather than argv, so it no longer shows in `docker compose ps`, + # `docker top`, or crash reports. --metrics serves /ready and /metrics on + # the compose network only; the image is distroless (no shell), so tunnel + # readiness is probed from another container, not by a healthcheck here. command: - tunnel - --no-autoupdate + - --metrics + - 0.0.0.0:2000 - run - - --token - - ${CLOUDFLARED_TOKEN:?set CLOUDFLARED_TOKEN} + environment: + TUNNEL_TOKEN: ${CLOUDFLARED_TOKEN:?set CLOUDFLARED_TOKEN} + expose: + - "2000" depends_on: app: condition: service_healthy diff --git a/docs/deployment.md b/docs/deployment.md index f81bf36..a66d0c7 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -27,6 +27,15 @@ the Compose network: Service: http://app:3000 ``` +The connector reads its token from the `TUNNEL_TOKEN` environment variable +(Compose maps `CLOUDFLARED_TOKEN` to it), so the token never appears in +`docker compose ps` or `docker top`. It also serves its metrics endpoint at +`http://cloudflared:2000` inside the Compose network: `/ready` returns 200 +only while at least one connection to the Cloudflare edge is registered, and +`/metrics` is Prometheus text. Neither is published on a host port. The image +is distroless, so there is no in-container healthcheck; readiness is checked +from another container. + ## Database and migrations The schema is loaded from `db/schema.sql` on first Postgres startup. Existing