Static Hosting with Caddy
Caddy serves the built static tree with automatic TLS. The repo ships one Caddyfile example (deploy/chinaski.Caddyfile.example) that you copy and edit per deployment — Caddy has no instance templating, so each instance’s site needs its own domain, upstream CMS address, output paths, and any language subdomains.
The essentials in the shipped example
- Site instances and ports: instance “1” → 3001, “2” → 3002 … — always matching
/etc/chinaski<N>/env’s LISTEN_URL (loopback, so clients never talk to the CMS daemon directly). - Sales-required routes even on a static site: reverse-proxy
/forms/*and/documents/*to the CMS daemon (else form submissions 404 and document URLs 404). - Honeypot paths (
/.env,/.git/config, wp-login probes etc.): routed through to the CMS so hits are logged and tarpitted rather than answered with a generic static 404. - Explicit X-Forwarded-For/Proto/Host headers on the proxy blocks — the production checklist calls these out for the app to see real client IPs; loopback-proxying is trusted by default, so no
CHINASKI_TRUSTED_PROXIESneeded unless your hop is through a container bridge. - Cache headers (same as the nginx example): HTML 5-min-revalidate;
sw.jsno-cache; woff2 fonts 1-year immutable; other assets 86400. - Belt-and-braces security headers in the proxy config (the app sets its own too).
Multiple instances
Copy the example per instance and adjust: each site block’s domain list (admin + language vhosts), upstream port (3001 for instance 1, 3002 for instance 2, and so on), and document root paths per language (/var/www/chinaski1/output/en for English, …/es for Spanish, etc.).
TLS
Caddy obtains and renews TLS automatically when DNS points at the host and ports 80/443 are reachable — verify with a curl -I https://<admin-host> once the Caddyfile is live.