# Tx OS — Caddy reverse proxy + TLS termination (HTTPS_MODE=local|byo). # # This Caddyfile is the default. The compose `caddy` service entrypoint # loads docker/Caddyfile.skip instead when HTTPS_MODE=skip, so this file # can assume TLS certificates exist in /certs. # # The site MUST stay single-origin so the API session cookie # (sameSite=lax) keeps working across SPA + /api requests. { # Disable Caddy's automatic Let's Encrypt issuance — we always # bring our own cert (mkcert locally, real cert in BYO mode). auto_https disable_certs admin off } (api_proxy) { # WebSocket / Socket.IO upgrade for /api/socket.io @websocket { header Connection *Upgrade* header Upgrade websocket } reverse_proxy /api/socket.io/* api:8080 reverse_proxy /api/* api:8080 } (spa_proxy) { # Static SPA bundle is served by the `web` container (nginx-alpine) # on port 80 inside the docker network. Caddy is the public edge. reverse_proxy web:80 } # ---------- HTTPS site (default) ---------- {$LOCAL_DOMAIN:tx.local}, {$LOCAL_IP:127.0.0.1} { tls /certs/local-cert.pem /certs/local-key.pem encode zstd gzip import api_proxy import spa_proxy } # Catch-all HTTPS host (covers raw IP / Tailscale name without # touching the named site). :443 { tls /certs/local-cert.pem /certs/local-key.pem encode zstd gzip import api_proxy import spa_proxy } # Plain HTTP → permanent redirect to HTTPS. Skip-mode (no certs) is # handled exclusively by docker/Caddyfile.skip, picked by the compose # entrypoint when HTTPS_MODE=skip. :80 { redir https://{host}{uri} permanent }