Updates

The appliance never fetches an update. You upload a signed release bundle; the daemon verifies its Ed25519 signature and runs the preflight before anything is applied, then hands the apply to a detached systemd unit that survives the control-plane restart. Tape I/O is not affected by a control-plane update. If the new binary does not pass its health probe, the updater rolls back on its own.

GET /api/system/update-status

read-only

curl -sk https://appliance:8443/api/system/update-status -H "Authorization: Bearer $OVTL_KEY"
{
  "version": "v1.0.0",
  "build": "2026-09-01T18:22:40Z",
  "pending": null,
  "last_good": {
    "from_version": "v0.9.3",
    "to_version": "v1.0.0",
    "binary": "/usr/local/bin/openvtld",
    "prev_binary": "/var/lib/openvtld/updates/openvtld.prev",
    "db_path": "/var/lib/openvtld/openvtld.db",
    "db_snapshot": "/var/lib/openvtld/updates/openvtld.db.prev",
    "attempt_limit": 3,
    "staged_at": "2026-09-01T19:02:11Z",
    "deadline": "2026-09-01T19:12:11Z"
  }
}

pending is the marker of an update that has been staged but not yet confirmed healthy; last_good is the record the rollback path uses. Either can be null. The paths shown are illustrative; read them from the response.

POST /api/system/update

admin Disruptive

A multipart upload, not JSON.

Form field Notes
bundle Required. The release .tar.gz. Bodies over 512 MiB are refused.
force Optional. 1 to apply a bundle that the version-ordering check would otherwise refuse.
curl -sk -X POST https://appliance:8443/api/system/update \
  -H "Authorization: Bearer $OVTL_KEY" \
  -F [email protected]
{
  "from": "v1.0.0",
  "to": "v1.0.1",
  "built": "2026-10-02T14:05:00Z",
  "unit": "openvtl-update-1759413900",
  "detail": "applying — the control plane restarts; tape I/O is unaffected. Progress: journalctl -u openvtl-update-1759413900"
}

202 means the bundle passed signature and preflight checks and the detached updater owns it from here. The daemon restarts; poll GET /healthz (public) until version reports the target. A bundle that fails verification or preflight is a 400 and is deleted. A bundle that also updates the data plane (kernel modules, the tape emulator) cannot be applied this way and is refused with a message telling you to run the installer in a maintenance window.

POST /api/system/rollback

admin Disruptive confirm: "rollback"

Reverts to the last-known-good binary and database snapshot through the same detached path. 400 if there is nothing to roll back to.

curl -sk -X POST https://appliance:8443/api/system/rollback \
  -H "Authorization: Bearer $OVTL_KEY" -H 'Content-Type: application/json' \
  -d '{"confirm":"rollback"}'
{
  "from": "v1.0.1",
  "to": "v1.0.0",
  "unit": "openvtl-rollback-1759414200",
  "detail": "rolling back — the control plane restarts. Progress: journalctl -u openvtl-rollback-1759414200"
}

The database snapshot taken before the update is restored with the binary, so anything changed between the update and the rollback is lost. Cartridge data on the pool is not touched.