# /etc/caddy/Caddyfile — RENDERED BY TERRAFORM for ${domain}. # Caddy provisions a Let's Encrypt cert on first request and auto-renews; the domain's # A/AAAA record must already point at this host and ports 80/443 must be open. # # The app owns the domain root and runs with THERMOGRAPH_BASE=/. Repo-split # Stage 4: backend (127.0.0.1:${port}) and frontend (127.0.0.1:${frontend_port}) # are two containers now -- path-split directly to whichever owns a given # path. Repo-split Stage 7a flipped which side owns the enumerated list: # backend owns the short, stable set below (mirrors backend/web/app.py's own # routing exactly -- a single catch-all proxy to frontend for everything # else), so the two never disagree about who owns what. # # NOTE: the repo's deploy/Caddyfile additionally serves the emigriffith.dev portfolio # and legacy redirects; those are host-specific and intentionally not templated here. # # Access-log hygiene: the default JSON encoder serializes full request headers, the # TLS block, and response headers on every line (measured ~1,133B/line on prod, # ~922B on beta) -- strip those with the `filter` format encoder. Also strip the # query string from the logged URI: Caddy's default logger records request.uri # *including* the query string, so every `?q=` a visitor typed sat in # Loki next to their client IP for the full 30-day retention -- a real privacy # leak, not just noise. Bot/crawler skipping stays out of here: `log_skip` needs # Caddy >= 2.7 and an upgrade is out of scope, so that's handled downstream in # Alloy's loki.process "caddy" stage instead (see observability/alloy/config.alloy). ${domain} { encode zstd gzip @backend_paths path /api/* /digest /discord/interactions # Active health check on the same cheap /healthz route each container's own # HEALTHCHECK uses (Dockerfile) — so a `docker compose up -d --build` deploy # that's still restarting/booting never gets proxied into (a reload alone has # no gate, hop-1 runbook hazard #10). health_uri is relative to the upstream. # 15s (was 5s): plenty responsive for an active health check against a process # that only restarts on a deploy, and a quarter of the polling load. handle @backend_paths { reverse_proxy 127.0.0.1:${port} { health_uri /healthz health_interval 15s health_timeout 3s health_status 2xx } } handle { reverse_proxy 127.0.0.1:${frontend_port} { health_uri /healthz health_interval 15s health_timeout 3s health_status 2xx } } log { output file /var/log/caddy/thermograph.log { roll_size 20MiB roll_keep 5 } format filter { wrap json fields { request>headers delete request>tls delete resp_headers delete request>uri regexp \?.* "" } } } }