Self-hosted VM orchestration, the Kubernetes way
A control plane for KVM/QEMU clusters with a declarative API, reconciliation loops and embedded etcd — engineered for long-lived, stateful VMs, not disposable containers.
curl -fsSL get.otherix.dev | OTHERIX_COMPONENT=cli sh
VMs aren’t cattle.
They remember.
Container orchestrators assume workloads are disposable replicas. Virtual machines aren’t — they’re long-lived, stateful entities. Otherix borrows the Kubernetes control-plane pattern but drops the assumption that you can throw the disk away.
Stable disks & identities
Disks persist across reboots, reschedules and migrations. Addresses and identities stay fixed. A VM is an addressable object, never a fungible replica.
Declarative, reconciled
A REST API with generation / observed-generation bookkeeping. Reconciliation loops converge the cluster to your declared spec — the Kubernetes pattern, minus the container assumptions.
Live migration, first-class
Move a running VM with a single change. Memory and disk stream peer-to-peer between agents; the control plane stays out of the data path.
A single binary, no external moving parts
Embedded etcd, no database
Embedded etcd is the only datastore the api-server runs — no Postgres, no Redis, no external queue to deploy or back up.
Single-binary agents
Each agent installs on a KVM/QEMU host as one static Go binary alongside qemu-system-*. It drives QEMU directly — no libvirt in the path.
Peer-to-peer live migration
Running VMs move host to host directly between agents over mTLS; the control plane orchestrates the move but never sits in the data path. Your open console and logs -f sessions follow the VM across the cutover, and so does its network identity, so a move costs milliseconds of pause rather than a reboot.
Replicated, self-healing snapshots
Point-in-time snapshots are standalone, content-addressed API objects — not shell scripts bolted on the side. Recreate a VM from one on any node (the disk is pulled peer-to-peer), set a replication factor to keep N copies across the cluster, and let it re-replicate after a node loss. Orphaned blobs are reclaimed automatically and bit-rot is scrubbed and re-replicated — durability is measured from what's actually on disk, never assumed.
Boot from a URL, cached cluster-wide
VMs boot straight from an image URL — no template object, no registry to run. Each node caches images content-addressed by digest, and a cached image is pulled peer-to-peer between nodes instead of re-downloaded, so the slow origin fetch happens about once per cluster. Pin exact bytes with a digest, or follow a rolling tag with a Kubernetes-style imagePullPolicy.
mTLS end to end
Every control-plane ↔ agent call is mutually authenticated. Agents join over mTLS and report observed state through signed heartbeats.
HA by self-clustering etcd
Run multiple api-server replicas; they form a single self-clustering etcd cluster and coordinate through it. No external quorum service to run.
A secure L2 fabric that follows your VMs
Overlay networks give VMs on different hypervisors a single layer-2 segment — a VXLAN tunnel riding an encrypted WireGuard underlay mesh. Because the segment spans the whole cluster, a VM keeps its MAC and IP when it live-migrates, and open connections survive the move.
Cluster-wide L2 overlay
VMs across nodes share one broadcast domain over VXLAN, isolated per VNI — no reliance on the physical fabric being flat.
WireGuard-encrypted underlay
Every inter-node frame rides an authenticated WireGuard mesh. The control plane recomputes the full peer set on each heartbeat — no agent-to-agent negotiation.
Deterministic forwarding
The control plane computes the forwarding database and hands it to agents on the heartbeat. VXLAN address learning is off, so the data plane never guesses. When a VM live-migrates, the control plane fast-pushes the updated map and the MAC re-points to the new node, with no flood-and-learn cycle.
One control plane, agents on every node
The control plane holds desired state in embedded etcd and reconciles it. Agents drive QEMU on bare metal and report back over mTLS.
From zero to a running VM
One command on a fresh Debian/Ubuntu server stands up a complete, fully functional single-node cluster — control plane, hypervisor agent, and a NAT network — then boots a demo VM you can SSH into. No config, no cluster wiring.
Done trying it? curl -fsSL get.otherix.dev/uninstall.sh | sudo FORCE=true sh removes everything and wipes all state.
Declare the cluster, apply it like kubectl
Describe networks, storage pools and VMs as otherix/v1 documents, then create or delete the whole set with one command — the same control-plane endpoints as the imperative flags, driven from a file.
Network, StoragePool and VM in a single otherix/v1 file, split by ---. Fields are camelCase; unknown keys are rejected, not ignored.
create -f always applies Network → StoragePool → VM so name references resolve; delete -f reverses it.
--dry-run prints the resolved plan; --wait blocks on VM tasks and pool reconciliation.
How Otherix compares
| Capability | otherix | Proxmox VE | OpenStack | Harvester |
|---|---|---|---|---|
| Model | Declarative desired/observed, Kubernetes-style reconciliation for VMs | Imperative cluster manager | Modular IaaS (many services) | HCI built on Kubernetes (KubeVirt) |
| Control-plane datastore | Embedded etcd, the only stateful service | Corosync + pmxcfs | SQL database + message queue | Kubernetes etcd + Longhorn |
| Hypervisor access | QEMU directly, no libvirt | QEMU/KVM | Nova via libvirt | KubeVirt (libvirt) |
| Live migration | Peer-to-peer between agents; the control plane orchestrates but is never in the data path — the guest’s network identity and live logs -f follow the move | Yes (cluster) | Yes | Yes (KubeVirt) |
| Snapshots & durability | Standalone content-addressed snapshots; cross-node replication, automatic reclamation and self-healing brokered by the control plane — no external storage system required | VM snapshots; ZFS / storage-level replication, PBS backups | Cinder volume snapshots & backups | Longhorn volume snapshots, backups & replicas |
| VM source | Image URL, no template entity | Templates / clones | Glance images | Images (URL / Longhorn) |
| Image distribution | Content-addressed node cache; images pulled peer-to-peer between nodes, Kubernetes-style imagePullPolicy — no registry or import service | Templates / clones on shared or local storage | Glance image service | Images via URL / Longhorn |
| Footprint | Single Go binary embeds etcd; no external DB | Per-node Debian + cluster stack | Heavy, multi-component | Full Kubernetes cluster |
| Operate & debug | Single binary, one log stream, no external services to correlate; plain Go and direct QEMU — few moving parts to debug or repair | Per-node daemons plus Corosync quorum to keep healthy | Many services plus DB and message queue to correlate; deep operational expertise | Full Kubernetes plus KubeVirt and Longhorn to operate and debug |
Reflects each project’s typical default architecture as of 2026. Capabilities, not endorsements.