FLEET
GitHub Docs

Zyvor · edge fleet control plane

Every site. Still running.

An offline-first control plane for Linux, Kubernetes, containers and virtual machines. The control plane declares what should run. A small fleet-agent pulls that desired state, caches the complete revision locally and keeps reconciling it when the WAN disappears, with no arbitrary remote shell.

QuickstartRead the docsHow it fits

Why Fleet

Remote sites fail in ordinary ways. Each row is something the README says Fleet does about it.

The WAN to a plant drops

The agent caches the complete desired revision (0600) and keeps reconciling drift locally. Events stay on disk and replay later.

Managing remote sites means an inbound port

Agents pull. There is no inbound management port and no generic server-triggered shell.

Every site mixes services, containers, k3s and a VM

One revision across four typed adapters: systemd, container (Docker or Podman), k3s and opt-in qemu.

A bad change hits every site at once

Strict wave rollouts with approval, windows, failure budgets, pause, resume, abort, retry and rollback.

A site is being serviced

Site cordons: the site keeps its last accepted state but is excluded from new rollout plans.

CI needs to drive rollouts

Scoped API tokens (read, sites:write, rollouts:write, admin) stored only as SHA-256 digests, plus HMAC-signed webhooks.

What it does

Control plane (fleetd)

  • Embedded console, no CDN
  • Email and password with PBKDF2, signed HttpOnly sessions, RBAC
  • Enrollment tokens that become independent per-site identities
  • Live inventory, dynamic label groups, declarative revisions
  • Bounded audit trail without request bodies
  • Prometheus /metrics, single-writer atomic JSON persistence, one binary

Offline-first agent (fleet-agent)

  • Pull-based, no inbound management port on the site
  • Complete desired revision cached locally
  • Local reconciling continues through WAN loss
  • Events queue on disk and replay on the next heartbeat
  • Per-site bearer identity; the enrollment token is not reused
  • No generic server-triggered shell
Typed runtime adapters and their safety boundary
KindBehaviorSafety boundary
systemdStart or stop a named unitValidated unit name; systemctl only
containerRun, replace or stop Docker or PodmanDeclared image, env, ports and args only
k3sAtomically maintain a k3s manifestValidated name; explicit manifest content
qemuStart or stop a basic KVM/QEMU VMDisabled by default; absolute disk path required

When sync fails, the agent marks the connectivity transition once, the cached revision stays authoritative, adapters keep reconciling drift, and queued events replay when the control plane returns. No control-plane call is needed to keep the last accepted desired state alive.

How it fits together

fleetd serves the web UI, REST API and rollout engine. Agents on each site connect outbound to it. Zyvor OTA devices use the same server for their assignment and event contract.

Fleet architecture A browser reaches fleetd over HTTPS. Three sites, each running a fleet-agent with typed adapters, pull from fleetd over outbound connections. Zyvor OTA devices use the OTA assignment and events endpoints on fleetd. Browser HTTPS fleetd embedded web UI · REST API · rollout engine auth / RBAC · audit trail · /metrics single-writer store Zyvor OTA devices /v1/devices/{id}/assignment /v1/devices/{id}/events outbound pull heartbeat · replay Site · fleet-agent cached desired revision systemd · container · k3s · qemu Site · fleet-agent cached desired revision systemd · container · k3s · qemu Site · fleet-agent cached desired revision systemd · container · k3s · qemu WAN down? Each agent keeps reconciling from its cached desired revision.
The qemu adapter is opt-in. v0.3 is a single-writer control plane; Kubernetes runs one replica on a ReadWriteOnce volume.
Maturity, stated plainly.

v0.3 is a serious single-writer release. Transactional HA storage, signed artifacts, agent OTA and air-gap OCI bundles are future milestones and are not present yet. Fleet is not a data or event plane, not general-purpose configuration management and not a cloud-vendor device registry. See the product plan.

Quickstart

Requires Go 1.27 or newer. These are the commands from the README; --demo is not for production.

1. Build

git clone https://github.com/zyvorai/zyvorai-fleet.git
cd zyvorai-fleet
make check && make build

2. Start the control plane

export ZYVOR_FLEET_ADMIN_PASSWORD='zyvor-fleet-demo'
export ZYVOR_FLEET_SESSION_SECRET='local-demo-session-secret-change-me-1234567890'

./bin/fleetd --demo

Open http://127.0.0.1:8080 and sign in as admin@zyvor.local with the demo password above.

3. Enroll a site

export ZYVOR_FLEET_ENROLLMENT_TOKEN='zf_enroll_demo-local-only'

./bin/fleet-agent \
  --server http://CONTROL_PLANE:8080 \
  --name factory-pune-01 \
  --region india-west \
  --labels class=factory,tier=production

4. Or try the Compose demo

docker compose up --build

Control plane plus two simulated sites. For Helm, systemd and the production checklist, see the deployment guide and the guided tutorial.

License

Fleet is free and open source under the Apache License, Version 2.0. Personal, lab and commercial production use at no charge, subject to Apache-2.0: preserve notices and the NOTICE file where required.

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