Built with Chinaski

cms.pl Reference

cms.pl is the Chinaski CMS daemon: it serves the admin interface and the API, while the public site is static HTML built separately. This page explains how to run the server in development, in production, and offline, plus the command-line tools that come with it.

Before you start

  • The server will not start without CHINASKI_SECRET. It is the signing key for admin sessions and protects the stored credentials for third-party services; set it to a long random value and never change it casually.
  • The admin session lasts 8 hours, and the cookie is only sent over HTTPS.

Running the server

Development

morbo cms.pl

Morbo is the development server: it restarts on code changes. Build the static site separately with perl builder/build.pl.

The deploy/ directory ships a templated systemd unit, chinaski@.service, so one set of files runs any number of CMS instances on the same host. Enable one with the instance name:

systemctl enable --now chinaski@1

(1 can be 2, prod, staging, anything alphanumeric.) What the unit does for you:

  • Runs as a dedicated chinaski user with the working directory /var/www/chinaski<instance>.
  • Sets the database and output paths automatically from the instance name (CHINASKI_DB, CHINASKI_OUTPUT); you normally don’t set those by hand.
  • Reads a single permission-locked env file, /etc/chinaski<instance>/env, which you create before starting. It must contain CHINASKI_SECRET and LISTEN_URL.
  • Restarts automatically on failure (with a backoff), waits for in-flight requests on shutdown (a 330-second drain; a build in flight is cancelled rather than waited out), and applies memory/CPU limits and standard hardening so a runaway build can’t starve the host.
  • Logs to journald: view with journalctl -u chinaski@<instance>.

Bind the server to loopback. In this setup a reverse proxy (Caddy or nginx) sits in front and the unit’s example binds LISTEN_URL to http://127.0.0.1:3001. The CMS only trusts forwarded client IPs from loopback connections; binding it to a public interface would let visitors spoof their IP and defeat the rate limits and login lockouts.

Production (no service manager)

Point deployments run during a deploy.sh <instance> run, which pulls code, installs dependencies, syntax-checks, rebuilds static output, and restarts the service. If a build fails, the deploy aborts by default so you never restart on top of broken output; CHINASKI_ALLOW_BUILD_FAIL=1 overrides this for emergency code-only deploys.

One-command server install

On a Debian/Ubuntu server you can stand up a new instance with a single command; the installer handles packages, dependencies, the chinaski user, database initialisation, the env file, and the systemd service:

curl -fsSL https://chinaski.net/install | sudo bash -s -- 1 --repo https://github.com/bigjohncobb/chinaski

Replace 1 with your instance name; pass --port PORT to override the default listen port.

Offline / “EOTW” mode (hypnotoad, plain HTTP)

For machines with no internet access (no DNS, no certificate authorities), hypnotoad can be the only server, serving plain HTTP on port 8080 forever.

  1. Build or obtain an offline bundle (bash install/make-bundle.sh on a connected machine) and follow the bundle install.
  2. Copy install/hypnotoad.conf into the application directory.
  3. Start it:
export CHINASKI_SECRET=$(openssl rand -hex 32)   # once; save the value
export CHINASKI_AIRGAP=1
hypnotoad cms.pl

Managing a running instance:

hypnotoad cms.pl                        # start, or hot-reload a running instance
hypnotoad -s cms.pl                     # graceful stop
kill -USR2 $(cat hypnotoad.pid)         # hot-reload without dropping connections

Two workers is safe on a 1 GB machine; raise to 4 on a 2+ GB host with multiple concurrent editors.

Security without a proxy: outside loopback, the CMS ignores X-Forwarded-For headers and uses the real TCP connection address, so rate limiting and login lockout work correctly with no extra configuration. There is no TLS in this mode: don’t send passwords over an untrusted network; use a VPN or firewall rules to restrict who can reach the admin.

Environment variables

Variable Purpose
CHINASKI_SECRET Required. Session signing key (32+ random bytes); also unlocks the encrypted credentials the CMS stores
CHINASKI_LISTEN Address the server listens on; default http://127.0.0.1:8080
CHINASKI_WORKERS Number of server workers; default 2. Use 4 on 2+ GB machines with several simultaneous editors
CHINASKI_DB Database file location; usually derived from the instance name by the systemd unit
CHINASKI_OUTPUT Static build output directory; usually derived from the instance name
CHINASKI_AIRGAP Set to 1 to disable every outbound request: build webhooks, form webhooks, and bot-check verification (the checkbox protection is also hidden)
CHINASKI_TRUSTED_PROXIES Comma-separated IP addresses or IPv4 CIDR ranges allowed to forward client IPs. Loopback is always trusted; default is loopback only
CHINASKI_ALLOW_BUILD_FAIL Set to 1 in front of deploy.sh to allow code-only deploys when a build fails
CHINASKI_FORCE_FULL Used internally by the full-rebuild command; not normally set by hand
MOJO_MODE Set to production in production deployments (the systemd unit does this); test mode changes the password hashing to a faster, test-only cost

Other variables exist in the code (CHINASKI_CMS_URL, CHINASKI_DOCS_DIR, CHINASKI_RELEASE_PUBKEY, CHINASKI_SMTP_INSECURE_NOVERIFY, CHINASKI_UPDATE_MANIFEST_URL, CHINASKI_URL_BASE, CHINASKI_FORCE_PROMOTE) but their exactly supported settings aren’t covered in these docs.

Command-line utilities

All live in bin/ and read the same database the CMS uses.

Command What it does
perl bin/chinaski-setup.pl Scripted first-boot setup. Pass --username, --site-url, and --password, or use the CHINASKI_ADMIN_PASSWORD environment variable instead, so the password isn’t visible in the process list. Applies the 12-character minimum plus the complexity rules.
perl bin/reset-admin.pl [username] Puts an administrator’s account back into first-boot setup mode so a new password can be chosen; requires shell access and a typed YES confirmation. The next visit to the site goes through the setup screen.
perl bin/chinaski-config.pl get KEY / set KEY VALUE Read or write any site setting from the command line.
perl bin/force-full-build.pl Clears the build cache and runs a complete static rebuild.
perl bin/check-schema-sync.pl Confirm the database matches the shipped schema; exit 0 means in sync, 1 means drift. Useful after upgrades.
bin/cron-build-monitor.sh Cron script (intended for every 5 minutes) that alerts when builds stop completing or pages vanish from the output directory.
Read this site in