Appliances and the pull model
Load balancers, gateways and object-storage nodes are ordinary virtual machines running ordinary open-source software. zone9 calls them appliances. They all follow the same lifecycle, so learning it once covers all three.
Configuration is pulled
Section titled “Configuration is pulled”The control plane never opens a connection to an appliance. Instead:
appliance control plane───────── ─────────────GET /v1/lb/config ────────────────► If-None-Match: "v12" ◄──────────────── 304 Not Modified (nothing changed) ◄──────────────── 200 { version: 13, … } (new intent)
apply locally, thenPOST /v1/lb/status { applied_version: 13 } ►Consequences, each of which is a design goal rather than a side effect:
- No inbound access to your machines. The panel does not need a route, a key or a port into the appliance’s network.
- Panel downtime is survivable. An appliance that cannot reach the API keeps running its last configuration. A load balancer keeps balancing.
- Convergence is observable. The appliance reports the version it applied. Comparing it with the intended version is exactly the applying / applied distinction described in Intent, truth and reconciliation.
- Polling is cheap. An unchanged configuration costs one conditional request every
few seconds and returns
304.
Identity: how a fresh VM proves who it is
Section titled “Identity: how a fresh VM proves who it is”A newly cloned VM has no credentials. It obtains them once, at first boot, through a channel that cannot be intercepted from inside another guest:
- When the VM is created, the panel mints a single-use bootstrap token and places it in the VM’s SMBIOS serial field — hypervisor-level metadata, readable from inside that guest and nowhere else.
- On first boot the appliance reads it and exchanges it for a long-lived device identity.
- The bootstrap token is consumed at that moment and is worthless afterwards.
- Everything from then on uses the device identity, which is stored only on that VM and only as a hash in the panel.
If a VM is rebuilt, the operator issues a new bootstrap token; the old device identity is retired.
Appliances are locked
Section titled “Appliances are locked”Appliance images are built without an SSH daemon, without a login shell on the console, and with no user accounts at all. You cannot log into a zone9 load balancer, and neither can anyone else.
This is a real trade-off and it is worth being explicit about both sides:
- What you lose: you cannot hand-edit the configuration. If HAProxy needs a directive the panel does not expose, the answer is to add it to the panel, not to the VM.
- What you gain: the machine’s state is entirely determined by what the panel sent. There is no configuration drift, no forgotten manual change, no credential sitting in a shell history, and no interactive access to compromise. Rebuilding an appliance is routine, because there is nothing on it worth preserving.
Diagnostics come from the appliance’s own status reports and from the hypervisor console, which shows the boot log.
Updating
Section titled “Updating”Appliances run a small updater on a timer. It compares the published release with the running version, and when they differ it downloads the new binary, verifies its checksum, executes it once to confirm it reports the expected version, keeps the old binary as a fallback, restarts the service, and rolls back if the service does not come back up. Two updaters cannot run at once.
Nothing is pushed here either: the appliance decides when to look.
Not appliances: Kubernetes nodes
Section titled “Not appliances: Kubernetes nodes”Managed Kubernetes nodes run Talos Linux, which has the same philosophy — an API-driven, immutable operating system with no shell — but its own mechanism. They are configured through Talos’s own machine-configuration channel rather than the pull loop described here, and they never talk to the zone9 API at all. A cluster does not know the panel exists.