Skip to content

Updates & rollback

hal0 updates itself in one atomic symlink swap, backed by cosign-verified release tarballs. If an update goes wrong, one command rolls back to the previous version.

The filesystem layout (PLAN §2) is FHS-aligned and deliberately separates the code from the data:

/usr/lib/hal0/current/ # symlink → /usr/lib/hal0-<version>/
/usr/lib/hal0-0.9.7/ # versioned install
/usr/lib/hal0-0.9.8/ # versioned install (next)
/etc/hal0/ # config, preserved across updates
/var/lib/hal0/ # models, registry, OpenWebUI state

hal0 update unpacks the new version next to the current one, then swaps the current symlink in a single rename(2) call. The systemd units point at /usr/lib/hal0/current/, so a restart picks up the new version atomically — no partial state on disk, ever.

Terminal window
hal0 update --check

Returns the latest version on the configured channel without applying it.

Terminal window
hal0 update # stable channel
hal0 update --channel stable # explicit
hal0 update --channel nightly # bleeding edge

The flow:

  1. Fetch the release manifest from hal0.dev.
  2. Verify the manifest signature.
  3. Download the version tarball.
  4. Verify the tarball against signer_identity + signer_issuer (GitHub OIDC, cosign).
  5. Unpack to /usr/lib/hal0-<new-version>/.
  6. Swap /usr/lib/hal0/current/ to the new version (atomic).
  7. Restart hal0-api.service.
  8. Slot units survive the restart — they keep serving traffic throughout.
Terminal window
hal0 update --rollback

Points current back at the previous versioned directory and restarts. The data dirs (/etc/hal0, /var/lib/hal0) are untouched, so your config, models, and registry are preserved.

ChannelWhat you get
stableCut releases. The default; recommended.
nightlyEvery green main build. For testing only.

Channels are configured in hal0.toml. Switch with hal0 config edit or via the dashboard’s Settings view.

The naive approach — tar xf … && systemctl restart — has two failure modes that bite at 2am:

  • Partial unpack. Disk fills mid-tar; you have half a new version overlaid on the old one. Nothing works.
  • Restart loop. New binary crashes on start; systemd retries; no obvious way back without a second SSH session and a working mv.

Atomic symlink swap solves both: the new version is fully unpacked before the swap, and the previous version is still on disk for --rollback to point back at.