Static Hosting with nginx
nginx serves the built static tree and forwards two URL families to the CMS daemon. The repo ships two example vhosts; this page covers both and the deploy-time root sync.
The two example files
deploy/chinaski.nginx.example— the minimal static vhost: document root, /forms/ and /documents/ proxy blocks, cache policies, and security headers.deploy/chinaski.nginx.conf.example— the fuller per-instance example (port 80 by default; add TLS viacertbot --nginx -d YOUR_DOMAINafter enabling the vhost).- Symlink into
sites-enabled/, runnginx -t, then reload (systemctl reload nginx) after configuration.
The document root
Point root at the built output:
/var/www/chinaski<N>/output/<lang>— for path-based multilingual (individual language vhosts; e.g. one per language site)./var/www/chinaski<N>/output— for monolingual sites (thenoneURL mode).
The deploy script auto-corrects the nginx root for you: on every deploy, deploy.sh rewrites the root directive in any nginx config referencing that install directory to match the current language mode (only output for none; else output/<default language>), runs nginx -t, and reloads — with a warning if the config test fails so you know to review manually.
Proxy blocks you need
location ^~ /forms/proxies tohttp://127.0.0.1:CMS_PORT— required when any form on the site publishes submissions (or renders any form at all). Without it: “every form submit returns 404”.location ^~ /documents/— required when the site uses the documents feature; documents’ download tracking and publish state can’t be embedded in a static build.
Other static paths need nothing beyond try_files $uri $uri/index.html =404 (plus per-asset cache directives and security headers).
Cache headers the examples set
- HTML — short maximum (5-minute revalidate), so published content is timely.
- Service worker — no-cache (
sw.js). - Fonts — 1-year immutable.
- Other assets — 1 day.
- Security headers — as belt-and-braces: the app sets them too; the proxy adds a layer for responses before the app gets a chance.
Loopback proxying (and why it requires no extra config)
The examples proxy from 127.0.0.1 — loopback, trusted by default in the app. If your real environment proxies to the CMS from a non-loopback address (a container bridge, for example), add that network to CHINASKI_TRUSTED_PROXIES so real client IPs are logged and rate limiting works per visitor.