ZYVOR OTA
Signed, recoverable device OS updates
The safest open OTA runtime for Linux edge fleets โ signed updates, automatic rollback, and verifiable evidence, without cloud lock-in.
-
15-minute trial
Enroll one device, ship a signed release, and watch commit or rollback.
-
Roadmap
What the agent implements, and which hardware claims stay unsigned.
-
User Guide
A single-page reference for the otactl CLI (zyvor-ota alias), the zyvor-otad daemon, and every agent.json field.
-
Architecture
The full job state machine and the invariants that guard it, from acceptance to commit or automatic rollback.
-
FAQ
Licensing, support, and production-readiness questions people ask before adopting it.
-
Lab stack
Deploy and wire OTA with Fleet, Nodra, Device Agent, and relay-edge on one Linux host.
It is not a fleet dashboard, not a targeting/rollout controller, and not a general configuration manager โ Zyvor Fleet (or whatever system you point it at) decides which devices get which release and when; OTA only ever verifies and installs. This repository contains a working Go agent and CLI, a native RAUC D-Bus adapter, an isolated simulator, and automated tests โ physical board qualification is a separate release gate.
See the full README on GitHub for the project overview, comparison table, and license details.
Take a closer look¶
Every release is an Ed25519-signed envelope checked against a pinned device trust key. The artifact is verified by SHA-256 digest and size after download, and the verified cached bytes are hashed again immediately before installation โ RAUC is only ever handed a bundle after signature verification passes.
RAUC owns the flash operation onto the inactive rootfs slot. Health
checks run after reboot; a healthy boot commits, and a deadline exceeded
or failed health check triggers automatic rollback to the previous slot.
A crash that leaves the outcome ambiguous enters NeedsRecovery instead
of guessing, and blocks further jobs until an operator resolves it.
What's implemented¶
- ๐ Ed25519-signed release envelopes, pinned device trust keys
- ๐งฎ SHA-256 digest and size verification, re-checked before install
- ๐ Automatic, health-check-gated rollback
- ๐งฏ
NeedsRecoveryinterlock for ambiguous post-crash states - ๐๏ธ Durable single-writer SQLite journal (WAL); terminal jobs archive, unacknowledged events stay
- ๐ฆ Schema 2 targets for OS, container, config, and model bytes, committed or rolled back as one set
- ๐ก Site relay, offline campaign, and local media, all checked by the same digest
- ๐ Unix-socket operator API, CLI, backup, archive, and Prometheus text metrics
- ๐ Optional threshold root and delegated keys when
trust_diris set. Not a conformance claim
- Exactly two bootable rootfs slots are supported per device; kernel/DTB partitions are grouped under their rootfs in RAUC. See installation and boot. ↩
- The 12 September 2026 report counted 71 passing Go test/subtest records with the race detector. Later commits added journal, relay, campaign, and supply-chain tests. See the report for that run; do not treat 71 as a current census. See the verification report. ↩
- The SQLite journal keeps 10,000 hot jobs. Older terminal jobs are archived in the same transaction. Unacknowledged events are not dropped. See persistence. ↩
- Install is RAUC D-Bus calls only (InstallBundle / GetSlotStatus / Mark) โ no shell commands or arbitrary update scripts are accepted by OTA. See the security FAQ. ↩