Updating Vloud
Release types, auto/manual settings, blue/green canary apply, rollback, and what to do when an update fails.
How releases are published, how your engine learns about them, the auto-update controls, the canary apply mechanism, and rollback.
Two surfaces, one mental model
Your dashboard has two update-related pages:
- System → Updates — the apply surface. Shows the current engine version, the latest available release, an Update Now button, and the full release history.
- Settings → System Updates — the policy surface. Master switch for automatic updates + per-type allow-list (Critical / Patch / Feature / Engine). The auto-update worker reads these before deciding to apply anything unattended.
The fix-notification banner that appears at the top of every page when a reported bug is fixed routes to the apply surface with the fix version pre-highlighted.
Release types
| Type | What it carries | Default auto-apply? |
|---|---|---|
| CRITICAL | Security fixes. | On (recommended). |
| PATCH | Bug fixes, no schema changes. | Off — flip on once you trust the channel. |
| FEATURE | New capabilities. May add migrations. | Off — typically manual. |
| ENGINE | Engine-process version bumps. May restart core services briefly. | Off — high-blast-radius. |
How your engine learns about updates
Every 6 hours, the engine’s heartbeat client calls POST /v1/updates/check on the Vloud license-server with your license id and current binary version. The server responds with the latest release that matches your tier and rollout cohort (a deterministic hash of your license_id mod 100; staged rollouts ship to a fraction of customers first to catch regressions before wider exposure).
The cached release is stored in vloud_update_releases with the manifest signature verified at insert time. If the signature doesn’t verify, the row never lands — the engine won’t offer an update it can’t prove came from Vloud.
Notifications
- Update available — System → Updates shows the new version in the “Latest available” card with a release-notes link.
- Fixed bug → update available — for releases that carry a fix for one of your reported bugs, an emerald banner appears at the top of every page until you dismiss it or apply the update.
Manual apply (the safe default)
- System → Updates → click Update Now.
- The engine kicks off a blue/green canary:
- Downloads the new tarball + verifies sha256 + Ed25519 signature.
- Extracts to
dist.new/. - Spawns the new engine on port 2501 (green slot).
- Healthchecks
http://127.0.0.1:2501/api/healthfor 30 seconds. - If healthy: atomic swap —
dist/→dist.old.<seq>/,dist.new/→dist/, restart on the canonical port. - If unhealthy: abort, leave the live process untouched.
- Live progress feed is in the apply panel. Stage transitions:
downloading→verifying→installing→restarting→completed(orfailed).
Failed canary doesn’t leave you with a broken engine — the atomic swap only happens after the healthcheck passes. Audit rows capture the failure reason (preflight-blockers, spawn, green-healthcheck, etc.) so triage is straightforward.
Upgrade from the command line
Prefer the terminal, or scripting upgrades across a fleet? The same installer upgrades an existing engine in place:
curl -fsSL https://install.vloud.app | sudo -E bash -s -- --upgrade
It is non-destructive: your database, /etc/vloud.env, licence
state, and every tenant account are preserved. The installer stages the
new release, runs the same sha256 + Ed25519 signature verification,
health-checks the new engine before the atomic swap, and rolls back
automatically if it doesn’t come up. Running the installer with no
flag (curl -fsSL https://install.vloud.app | sudo -E bash) also
auto-detects an existing install and upgrades it — --upgrade just
makes the intent explicit.
It upgrades to the latest release on your engine’s channel (currently
the newest -beta build). To land a specific version instead, see
Pinning to a specific version below.
Automatic updates
Settings → System Updates → toggle Enable automatic updates + tick the types you trust. The auto-update worker polls every hour. If a release matching one of the enabled types is available AND the rollout cohort includes you, it applies the same blue/green flow described above — no human in the loop.
Recommended starting point: enable auto-update for CRITICAL only. After a few weeks of clean auto-applies, add PATCH. FEATURE and ENGINE typically stay manual unless you have a low-stakes install you can dogfood with.
Rollback
Every successful apply preserves the previous engine tree at dist.old.<seq>/. The engine keeps a 3-slot ring (configurable). To roll back:
sudo vloud-update rollback # interactive picker
sudo vloud-update rollback --to v0.0.1 # specific version
The rollback is itself an atomic swap. After the swap, an integrity check re-hashes dist/index.js against SHA256SUMS; mismatch → exit 21, systemd hits StartLimit, safe-mode auto-engages on the next boot.
Settings → Updates → Rollback options (in the dashboard’s Admin section) lists the available slots with version + applied_at timestamps, and the dry-run lets you preview the swap before executing via the CLI.
What “failed update” means
Three distinct failure modes, each leaves you in a different state:
- Pre-flight reject. Signature didn’t verify, or the manifest’s sha256 doesn’t match the tarball. The engine refuses to extract — your install is untouched. Re-check the mirror or wait for a re-publish.
- Canary fails healthcheck. The new engine starts but doesn’t answer
/api/healthwithin 30 seconds. Swap aborts; live process untouched. Audit row capturesgreen-healthcheckfailure for triage. - Migration fails after swap. Rare. The new engine starts but a SQL migration throws. Better-sqlite3 wraps each migration in a transaction so partial state is impossible, but the engine fails to boot. Three consecutive boot failures → safe-mode auto-engages, the dashboard renders, and you can recover via vloud-rescue.
Release channels
Vloud is currently on the beta channel — new engine builds ship as
X.Y.Z-beta (for example 0.9.2-beta). The release protocol supports
separate beta and stable channels, each with its own release
history; both the dashboard and the --upgrade command follow your
engine’s channel, so a beta engine sees beta releases and a stable
engine sees stable ones.
Pinning to a specific version
For installs that need to reproduce an exact build, the release host serves per-version pinned URLs. Today’s example:
https://install.vloud.app/releases/v0.9.2-beta/vloud-0.9.2-beta.tar.gz
Set VLOUD_RELEASE_URL to the pinned URL during bootstrap and the engine installs that exact version. Browse https://install.vloud.app/releases/ or fetch https://install.vloud.app/releases/index.json for the machine-readable history.
What signed updates protect against
- MITM tampering of the tarball in flight (sha256 + JWS catch this).
- A compromised mirror serving altered bytes (signature verification fails before extract).
- A signed-but-stale or repurposed signature (artifact-name cross-check refuses if the signed-payload artifact differs from the on-disk filename).
What signed updates don’t protect against: a compromise of the Vloud signing key itself (mitigated by KMS-managed keys in canonical releases + a documented key-rotation path).