ADR-0004: Single ingress (Caddy), Cloudflare only at the public edge
Synced read-only from
/home/synnet/synvirt-platform/docs-internal/adr/0004-single-ingress-caddy.md. Edit at the source, not here.
ADR-0004: Single ingress (Caddy), Cloudflare only at the public edge
Section titled “ADR-0004: Single ingress (Caddy), Cloudflare only at the public edge”- Status: Accepted
- Date: 2026-06-28
Context
Section titled “Context”We want one place that routes every subdomain, segmented internal networking,
and the ability to move a service to another host by changing one upstream. We
also need a real public certificate plus WAF/Turnstile for synvirt.mx.
Decision
Section titled “Decision”Caddy is the only ingress in both dev and prod; it is the only service that
publishes host ports (80/443). Postgres, Redis, Meilisearch, MinIO and Keycloak
stay on the internal network with no published ports (dev binds a few to
127.0.0.1 only, for host-run apps).
- Dev: Caddy uses an internal CA (
tls internal) for*.synvirt.test, honoring the rule that internal services use Caddy’s internal TLS. - Prod:
synvirt.mxis public. Cloudflare provides DNS / WAF / Turnstile and a Tunnel to Caddy; Caddy (or Cloudflare) terminates real TLS. Cloudflare is decoupleable — Caddy remains the single entry point either way.
Consequences
Section titled “Consequences”- Moving a service to another host = change one
reverse_proxyupstream. - Nothing sensitive is exposed; only the public web/API/auth vhosts are reachable.
- Two Caddyfiles (
Caddyfile.dev,Caddyfile.prod) keep dev (host upstreams viahost.docker.internal) and prod (container upstreams) cleanly separated.