Built with Chinaski

SSH / rsync Deploy

Chinaski can push its freshly built static site to a remote host after every successful build, over SSH, using rsync. You configure one target, and every build ends with the output mirrored to that host. This page covers setup, the safety rails, and failure behavior.

Setup

Under Settings → Deploy, two switches decide whether a deploy fires automatically:

  • Deploy automatically after a successful build is the master switch. Off by default; both rsync deploy and S3 deploy stay dormant until this is on, even if their own settings below are fully configured.
  • Enable SSH/rsync deploy (also off by default) turns on this specific target once the master switch is on.

Then fill in:

  • Host: a hostname like web01.example.com (letters, digits, dots, hyphens only).
  • User: the SSH account (optional; omit to use the account already known to your local ssh config).
  • Remote path: the destination directory, absolute only (/var/www/site, no spaces).
  • SSH key path: the private key on the CMS host used to authenticate (optional, your ssh config may already pick one up; if set, it must also be an absolute path with no spaces).

After configuring both switches, save; deploys happen automatically at the next successful build. If your settings fail validation (a space in the path, a relative key path, shell metacharacters anywhere), the deploy is simply skipped rather than half-run.

What actually happens

After a build promotes its output, the CMS launches a background rsync of the live output directory to the destination:

  • The command shape is rsync -az --delete over SSH: archive mode, compression, and exact mirroring (stale files removed on the target).
  • SSH connects non-interactively (BatchMode), key-based authentication only, no password prompt. Set up the destination host for key auth out of band.
  • First connections auto-accept the remote host’s fingerprint (accept-new); subsequent connects verify against the remembered key.
  • Runs in the background: a deploy doesn’t hold up the build’s bookkeeping, and the build’s success is independent of the deploy’s.

In air-gap mode all of this is disabled. The deploy never runs regardless of configuration.

Validations built in

Deploy settings are guarded ahead of execution:

  • Host and user: no shell metacharacters (; | & \ $ quotes etc.), plausible hostname characters only.
  • Remote path and key path: must both start with /, must not include shell metacharacters or spaces.
  • Anything failing validation means the deploy silently runs nowhere, with a log line; the site itself still built and serves locally.

Status in the admin

While a deploy is running, the admin shows a live status banner (polling every few seconds) that walks through “Building your update…” to “Build complete. Publishing your update…” to “Your update is live.”, or an error state if the build or the deploy failed. The banner is driven by the deploy’s actual state, not a timer, so it keeps showing “publishing” for as long as a sync is genuinely still running, including a slow upload over a poor connection. It won’t disappear early just because a deploy is taking a while.

Failures and what to look for

Deployment outcomes appear in the journal (journalctl -u chinaski@<N>):

  • rsync deploy failed (rc=N): …: the exact reason line; common causes are unreachable host, auth failure (key not authorized on the target), or missing/incorrect remote path.
  • rsync deploy complete -> user@host:/path: the clean success.

A failing deploy never affects the site content on the CMS host. The previous output continues to serve; retry by triggering a rebuild or fixing the SSH access and rebuilding.

The sibling: S3 deploy

A second outbound channel uses the same build pipeline: S3 deploy (bucket, endpoint, region, access key, secret key in Settings → Deploy), running via rclone after the rsync step. You can use either or both; both run on every successful build when enabled. All the deployment targets fire in the same order per build: webhooks first (build webhook), then rsync, then S3.

Read this site in