Built with Chinaski

Security by Construction

Chinaski doesn’t rely on you configuring security: the safe behavior is built in, and the lazy path is the secure path. This page explains what that means: protections that ship on, safeguards that are structural rather than optional, and honest notes about what still takes a conscious choice.

Protections that are simply on

Four defaults the stub line of this page names; you get all four with zero configuration:

  • Verified scripts and styles: every self-hosted admin asset is hash-checked (SRI) by the browser before it runs. A tampered library is refused, not executed.
  • Strict content policy: every admin response carries a nonce-based CSP: only server-tagged scripts run, nothing is framed by other sites, and a list of unused browser features (camera, microphone, geolocation, and friends) is disabled. No config; it’s just how responses are built.
  • No trust for forged IPs: rate limits and lockouts count you by a client IP the server can actually verify. Header-supplied addresses are believed only from a trusted proxy; anyone connecting directly gets their true address.
  • Lockouts that persist: repeated failed logins lock the source IP out for escalating windows (one minute, then five, then thirty), and the count survives restarts, so rebooting doesn’t reset an attack.

Safeguards that come from the shape of the system

Some security properties aren’t settings at all; they’re consequences of the architecture:

  • Your public site never runs the CMS code. The published site is plain files served by your web server; logins, forms, and uploads happen on a separate admin surface. A vulnerability in one doesn’t automatically put readers in the blast radius.
  • No runtime JavaScript on the public site: by construction, not promise. There’s no mechanism through which to add a tracker, beacon, or third-party script to your pages; there’s nothing to misconfigure.
  • Secrets are never readable in plain text. Credentials for email, cloud storage, and integrations are encrypted in the database with a key derived from the instance’s master secret; even the API never returns them.
  • Passwords use a modern, upgradeable hash. Hashing follows a managed library so the scheme can be strengthened over time without logging anyone out or rewriting accounts.
  • Privileges are enforced server-side. Roles and per-user content restrictions are checked on the server for every privileged action; the browser can’t be talked past them.
  • Abuse gets throttled everywhere it can happen: sign-in, registration, password recovery, form submissions, and API usage all have per-IP or per-key limits on by default, with deliberate slowdowns for abusive requests and honeypot URLs that log scanner probes.
  • The server runs boxed in. Systemd sandboxing makes the filesystem read-only outside the app’s own directory, blocks privilege escalation, and caps memory/CPU; the installer sets restrictive file permissions as part of setup, not as a manual follow-up.
  • The master secret starts owner-only readable. The file holding it is created with no group or world access before the server first runs.
  • Every sign-in, failure, lockout, and scanner probe is logged in a structured, greppable form, so “what happened” is answerable after the fact.

Sensible defaults where choice exists

Some protections are defaults rather than mandates, and that’s stated plainly:

  • Public form spam protection is on for new forms (verification widget); you can turn it off per form, but you have to choose to.
  • Self-registration is off. People can’t create their own accounts unless you enable it.
  • Cookies are Secure, HttpOnly, and SameSite with an 8-hour lifetime: admins are signed back out daily by design.
  • Airgap mode turns off every outbound call the server could ever make if your installation must be able to testify that it doesn’t telephone home.

What the project states about itself

Honest, stated positioning (from the project’s own documentation):

  • It is aimed in part at “security-focused organizations … where what you don’t ship matters as much as what you do.”
  • It “doesn’t telephone home”: no telemetry, no license validation, no CDN dependencies, no fonts fetched from anyone else.
  • Its small, stable, OS-packaged dependency list is itself the security posture, fewer, staler, slower-changing parts means a smaller attack surface than ecosystems that add packages by the hundred.

The principle on the page is plain: the person who forgets to think about security is the default beneficiary. Nothing on this list is opt-in except what is deliberately opt-out-able (the per-form bot check, self-registration, airgap toggles), and the documentation tells you which is which.

Read this site in