Operations
Update Noite, back up and restore its volumes, and troubleshoot ready gates and boot failures.
Releases and channels
Installs follow releases, not main. NOITE_IMAGE (or NOITE_VERSION for the installer) picks what an update pulls:
| Tag | What it is |
|---|---|
alpha |
The newest release of any kind. The default while Noite is alpha. |
stable |
The newest final release (no -alpha.N in its version). Absent until the first one. |
0.1.0-alpha.1 |
One release, pinned: an update changes nothing. |
short SHA, edge |
A build of main. Not for installs: for CI and rollbacks. |
Every release is tagged v<version> and passes the end-to-end lanes (passkey signup, invites, git push, deploys, and the hostile-tenant suite) before its image is published. Its notes are in CHANGELOG.md; each has an Operator action required section, even when it is “None”. Read it before you update.
To roll back, set NOITE_IMAGE to the previous version tag. That works across releases that did not change the database schema; a release that did refuses to be downgraded (see Troubleshooting), so take a backup first.
Updating
Re-run the installer, or pull and recreate by hand:
curl -fsSL https://noite.run/run.sh | bash -s install
# or
cd /opt/noite && docker compose pull && docker compose up -d
The image is disposable and state lives in the volumes and the bucket, so an update is a pull plus a recreate. The runner stops every fleet in parallel inside its stop budget (NOITE_STOP_BUDGET_MS, 25 s; Compose’s stop_grace_period is 35 s), then Caddy, then writes a final state snapshot. A new image restarts every tenant fleet with it (cold boots), so batch upgrades.
Stop-budget tuning lives in Environment variables.
Backups
A consistent backup snapshots the runner database, stops the stack, tars both volumes and starts again. Downtime is the tar time.
cd /opt/noite
STAMP=$(date -u +%Y%m%dT%H%M%SZ) && mkdir -p "backups/$STAMP"
docker compose exec -T noite sh -c \
'curl -fsS -X POST -H "Authorization: Bearer $RUNNER_TOKEN" http://127.0.0.1:8080/v1/admin/snapshot'
docker compose stop
for vol in noite-data rustfs-data; do
docker run --rm --entrypoint tar -v "noite_$vol:/vol:ro" -v "$PWD/backups/$STAMP:/out" \
ghcr.io/ryuzcorp/noite:alpha -cf "/out/$vol.tar" -C /vol .
done
docker compose up -d
With your own bucket, turn on versioning at the provider instead; rustfs-data then does not exist and only noite-data needs the tar.
Restore
cd /opt/noite
docker compose down
for vol in noite-data rustfs-data; do
docker volume rm -f "noite_$vol" && docker volume create "noite_$vol"
docker run --rm --entrypoint tar -v "noite_$vol:/vol" -v "$PWD/backups/<stamp>:/in:ro" \
ghcr.io/ryuzcorp/noite:alpha -xf "/in/$vol.tar" -C /vol
done
docker compose up -d
Compose warns that the volumes were not created by it; that is expected. Verify with docker compose exec noite curl -s http://127.0.0.1:8080/ready, then open an app.
Troubleshooting
- Boot stops with
refusing to start: the runner database is schema version N(or the same for the control database): the data was written by a newer Noite than the image you started. Run the newer image again, or restore a backup taken before the upgrade. Downgrading across a schema change is not supported, and the refusal is what stops an old image from damaging newer data. - Locked out after losing the passkey: see Lost passkey.
/readyanswers 503: its body names the failing gate (reconcile,bucket,isolation,control,caddy). A fresh install waits for the control bundle’s first deploy intos3://<bucket>/control(seconds; revision-gated, so a restart with the same bundle and vars skips it).isolation: …in multi: the container lacks a capability ornft. GrantNET_ADMIN,SETUID,SETGIDandCHOWN, or runNOITE_TENANCY=single.- Boot stops with
runner state restore failed: the volume is empty and the bucket did not answer. The runner refuses to start with an empty database (it would overwrite the good snapshot); fix the store and it retries on restart. - A deploy fails with
celld deploy does not support these config keys: a Wrangler key celld does not accept. Noite strips the keys it consumes (release,build) before deploying; anything else must go. - A deploy fails with
nothing to deploy: the tree has no Wrangler config, noindex.htmlindist/,build/orout/, and nopackage.jsonmain. See No config at all. - A deploy fails with
starts a Node HTTP server:package.jsonmaincalls.listen(). Noite runs Workers; see Frameworks and Node servers. - Many
429responses: the edge rate limits. Behind a proxy, checkNOITE_TRUSTED_PROXIES; otherwise raiseNOITE_EDGE_RPMor the app’s own limit (Edge protection).