ZYVOR OTA
GitHub Docs

Zyvor · device OS updates

Signed A/B updates. Commit or roll back.

The open OTA runtime for Linux edge fleets: signed updates, automatic rollback, offline operation and verifiable deployment evidence, without cloud lock-in. Fleet decides which devices and when. OTA verifies and installs. RAUC writes the inactive slot.

Run the simulator demo15-minute trialHow it fits

Why Zyvor OTA

Each row is a field problem and what the README says the agent does about it.

An update image could be tampered with or replayed

Ed25519-signed exact-byte release envelopes, pinned device trust keys, expiry, a monotonic release sequence and replay rejection.

A bad update bricks devices

Install to the inactive RAUC A/B slot, run a local health window, then mark good or roll back automatically.

The agent crashes mid-install

A durable SQLite (WAL) journal and an explicit NeedsRecovery interlock for ambiguous outcomes.

Sites have slow, metered or no WAN

Resumable HTTPS downloads, download windows, bandwidth caps, offline campaign media and a site relay client.

Security won't accept an inbound port

An outbound-only Fleet contract over TLS or mTLS, polling with ordered event acknowledgment.

An auditor asks what was installed

Prometheus metrics, optional OpenTelemetry spans, a signed SBOM check and an append-only release log.

What it does

Verify

  • Ed25519 envelopes over exact bytes, pinned device keys
  • SHA-256 and signed artifact sizes, exact board and backend compatibility
  • Expiry, monotonic sequence, job idempotency, maintenance windows
  • Optional threshold root, delegated targets, signed SBOM, release log

Install and survive

  • RAUC InstallBundle, Completed, GetSlotStatus, GetPrimary and Mark over D-Bus
  • Controlled reboot, local health window, mark-good or rollback
  • File, systemd-service and loopback HTTP health probes
  • No shell commands or arbitrary update scripts accepted

Offline and constrained sites

  • HTTPS downloads with host allowlists, bounded size, disk reserve and resumable ranges
  • Offline campaign export and import, local media, jitter
  • Site relay client

Operate

  • otactl CLI over a Unix-socket operator API (zyvor-ota is an alias)
  • Prometheus text metrics, optional OpenTelemetry spans
  • Schema 2 typed targets (os.rauc, container.oci, config.bundle, model.oci) commit or roll back as one set
Scope, as the README states it
CapabilityStatus
Simulator install, reboot and rollbackImplemented and software tested
RAUC D-Bus wire protocolImplemented; tested against a test service on a private bus
Real signed RAUC bundles on physical devicesAdapter implemented; board qualification required
Generic QEMU RAUC lab HILComplete
Minewing GW1 r1 siliconUnsigned
SWUpdate .swu, MCU firmware, TPM driverNot implemented

How it fits together

Fleet decides which devices and when. The agent verifies and installs. RAUC writes the inactive slot and integrates with the board bootloader. There is intentionally no second fleet dashboard or rollout controller in this repository.

Zyvor OTA update lifecycle Zyvor Fleet assigns a signed release to zyvor-otad over an outbound poll. The agent verifies and downloads it, then asks RAUC to install it into the inactive slot over D-Bus. After a reboot and a local health window, the update is committed, or the device rolls back to the previous slot. An operator can use otactl over a Unix socket. Zyvor Fleet decides which devices, when /v1/devices · /api/v1/ota poll ack zyvor-otad (device agent) verify signature · SHA-256 · expiry sequence · replay check · download SQLite journal · health probes D-Bus RAUC InstallBundle, Mark external dependency writes Inactive slot new release reboot Local health window file · systemd · HTTP probes Healthy: commit mark good Unhealthy: roll back previous slot is primary again otactl Unix-socket operator API
An ambiguous outcome after a crash raises the NeedsRecovery interlock instead of guessing.
Maturity, stated plainly.

v0.2.0 is an engineering preview: a working agent, CLI, RAUC adapter, simulator and CI, plus a complete generic QEMU RAUC lab HIL. Minewing silicon qualification is still unsigned. Not claimed: physical Minewing RAUC or power-loss qualification, Uptane conformance, a TPM driver, SWUpdate .swu, MCU firmware or bootloader updates. Evidence is in the verification report and the roadmap.

Quickstart

Requires Linux, Go 1.27.1 or a newer supported patch (Go 1.24 is the language minimum), Python 3 for the demo, GCC for race tests and dbus-daemon for protocol tests. These are the README's commands.

1. Build and run the simulator demonstration

make build
make test
make demo

The demo starts the real daemon and CLI against a local artifact server, installs two simulated releases, commits the first, rolls back the unhealthy second, and rejects replay. It never writes disks, calls system reboot or contacts a Fleet deployment.

2. Sign a release and submit it

otactl keygen ./release-keys
# Fill examples/release.json with the actual artifact URL, SHA-256, size and expiry.
otactl sign release.json release-keys/release.key production-1 envelope.json
# Embed envelope.json as the release field in assignment.json.
otactl -socket /run/zyvor-ota/agent.sock submit assignment.json
otactl -socket /run/zyvor-ota/agent.sock job job-001

Keep the signing private key off the device. Before using the RAUC backend on hardware, read device integration: the image must already provide redundant slots, a bootloader fallback policy and a recovery method. The guided tutorial walks the 15-minute trial.

License

Zyvor OTA is free and open source under the Apache License, Version 2.0. Use, modify and run it for personal, lab and commercial production use at no charge, subject to Apache-2.0 (preserve notices and the NOTICE file where required).

Original Zyvor OTA source is Apache-2.0. Vendored dependencies retain their own licenses (see THIRD_PARTY_NOTICES.md). RAUC is an external runtime dependency and is not relicensed by this project.

Support the project

Free under Apache-2.0. If it helps you, you can donate any amount you like: https://rzp.io/rzp/utwdYh3. A donation is voluntary and supports development and maintenance. It is not a purchase: it buys no support, SLA, features, priority or license, and it is not tax-deductible (Zyvor AI Labs Private Limited is a company, not a charity). Zyvor Enterprise (supported releases, SLAs, a named contact and enterprise features) is separate: sales@zyvor.dev.

Donate any amountLooking for enterprise support? Contact sales