Files
internal-server-gateway/docker-compose.yml
T
kongkxandClaude Opus 5 6379e8c147 feat: route project instances over the edge network
Project preview instances (gig-platform, gig-app) publish no host ports; they
join an external `edge` Docker network under instance-qualified aliases.

- Caddy joins `edge` and loads per-project sites from sites/*.caddy. It is the
  LAN entry: split DNS → Caddy → instance, by hostname label.
- New preview tunnel, `cloudflared-preview`, on `edge` only. It routes public
  instance hostnames straight to their aliases, so public previews do not
  depend on Caddy, and the connector cannot reach Caddy, the host or LAN
  services. The infra tunnel keeps fronting the host's own services via Caddy
  and has no route to instances.
- sites/gig-platform.caddy and sites/gig-app.caddy mirror gig-platform's
  docs/deploy/caddy/.
- The old host-port gig blocks move to sites/legacy-gig.caddy, to delete at
  gig-platform's main cutover.
- Global client-IP trust for requests arriving through cloudflared.

Validated with the custom Cloudflare-DNS build (`caddy validate`).

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MTExEkPpPMV4gSdfHpztra
2026-09-15 07:43:44 +08:00

70 lines
2.3 KiB
YAML

services:
caddy:
build:
context: .
dockerfile: Dockerfile
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3 (QUIC)
environment:
- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- default
# The LAN entry to project instances (split DNS → Caddy → instance).
# Instances join `edge` under instance-qualified aliases and publish no
# host ports.
- edge
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./sites:/etc/caddy/sites:ro
- ./data:/data
- ./config:/config
- ./site:/srv
# Infra tunnel: public hostnames of the host's own services, all through
# Caddy (https://caddy:443). Cannot reach project instances.
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN}
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
- caddy
# Preview tunnel: public hostnames of project instances (gig-platform main,
# its gates, gig-app main), routed straight to their aliases on `edge` —
# e.g. http://gig-platform-main-nginx:80. Cloudflare terminates TLS.
#
# A separate tunnel and connector on purpose:
# - public previews do not depend on Caddy, and restarting or
# reconfiguring one tunnel never touches the other;
# - `edge` is its only network, with no host-gateway, so this connector
# cannot reach Caddy, the host or LAN services, and a dashboard mistake
# on this tunnel can only ever expose something already on `edge`;
# - the infra tunnel, in turn, has no route to instances.
# PR and e2e instances stay LAN-only: never publish a wildcard on it.
cloudflared-preview:
image: cloudflare/cloudflared:latest
container_name: cloudflared-preview
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_PREVIEW_TUNNEL_TOKEN}
networks:
- edge
networks:
# Created once, outside any project, because every project attaches to it:
# docker network create edge
edge:
external: true