Deploy to Caddy
Caddy is Chinaski’s reference web server: automatic TLS, and two per-instance pieces of wiring: a site block that serves the static output, and the builder-generated redirect snippet included per site. This page walks through a production Caddy setup; the shipped Caddyfile example is the source copy to work from.
Prerequisites
- A running CMS instance (the
chinaski@<N>unit), daemon bound to loopback. - A built output directory per language (
/var/www/chinaski<N>/output/<lang>, oroutput/for monolingual sites). - The shipped example
deploy/chinaski.Caddyfile.exampleto copy.
Copy and adapt the example
Caddy has no instance templating, so each deployment gets its own edited copy. In the example, set per instance:
- The site’s hostnames (admin domain plus any language vhosts).
- The upstream port: the loopback address matching
LISTEN_URLin that instance’s env file (instance 1 → 3001, instance 2 → 3002). - The document roots: per-language output directories.
Caddy obtains and renews TLS certificates automatically once DNS points at the host and ports 80/443 are reachable, no certbot step. Verify with curl -I https://<host> after first start.
The forwards the example includes
A mostly-static Caddy site still forwards these to the CMS daemon on loopback:
/forms/*: public form rendering and POST handling. Without it, embedded form submissions return 404./documents/*: document downloads (the track-and-count path that a static file server can’t do).- Scanner honeypot paths (
/.env,/.git/config,wp-login.phpand friends); routed to the CMS so probes are logged and throttled rather than answered with a plain server 404.
The example also includes an installer-download route served straight from the deployment directory, handy for the documented curl installer URL pattern.
The proxy calls set X-Forwarded-For, X-Forwarded-Proto, and X-Forwarded-Host explicitly, which is the README production checklist’s own ask, and because the example proxies from loopback (trusted by default), no extra CHINASKI_TRUSTED_PROXIES is needed; only a container-network hop would require it.
Caching headers
The shipped block matches the standard cache policy (HTML short-cache revalidated per build; sw.js no-cache; fonts immutable year-long; other assets daily), and repeats the app’s security header set as belt-and-braces for responses served before the app can.
Including the generated redirects
After each build the builder writes _redirects.caddy at the output root: your slug redirects plus (when a Site URL is configured) the canonical domain enforcement in the same file’s _redirects. Include the Caddy-syntax snippet in each site block as the file’s own header comment directs; because Caddy’s canonical-domain line uses the 301! force marker, this file is meant for Caddy specifically (other hosts should review that syntax as described on the redirect-formats page).
Local-loopback trust means no extra config
The example proxies from 127.0.0.1, which the CMS already trusts, so client IP logging and per-IP rate limiting work with no extra settings. Should your topology instead proxy from a non-loopback address (a container bridge, for example), add that network to CHINASKI_TRUSTED_PROXIES so the real visitor IP is what gets logged and limited.