Releases

Tarballs and checksums for every release live at eitri.sh/dl, with /dl/latest/ pointing at the newest. The quickstart takes a release from download to a running VM.

v0.0.4

A PAT is enough. Point an LLM client anywhere on the internet at https://api.eitri.sh/mcp with a personal access token and it gets the whole eitri toolset: create a VM, run commands in it, publish a port, hand back the address. No local install, no config file, no CA of your own.

The MCP endpoint. eitri-server serves MCP at /mcp over streamable HTTP, stateless, authenticated with the same bearer token the API takes. One binary, one deploy: the tools call the API in-process, so tenant filtering and authorization are the API's own, and a caller sees exactly the fleet its token can see. The stdio binary is unchanged and still there for local use—both transports serve the same tools, from the same code.

An eitri-managed CA, if you ask for one. Bring-your-own tenant CAs stay the default, and a token holder has no key to sign with. So there is a register tool: eitri generates a signing key for your tenant, holds it, and signs a fresh five-minute certificate for each command it runs for you. The public half joins your CA set like an uploaded one—same label in the console, same behaviour at the gate. It is opt-in, idempotent, and DELETE /api/v1/managed-ca takes it back. As with any CA, a guest trusts the set it was created with, so VMs that predate register will not accept it.

Progress on the long call. vm_create waits for the guest to boot and cloud-init to settle, which can take minutes. It now reports what it is waiting for as it waits, so a model watching a ten-minute call sees a VM coming up rather than silence.

v0.0.3

macOS hosts. An Apple-silicon Mac joins the fleet as a host and runs Linux guests beside your Linux boxes (so the Mac Mini can earn its keep after all). Around it: hosts own their guest networks, you can publish a VM's ports, and the agent reads guest images without a conversion tool.

Mac hosts. An Apple-silicon Mac enrolls like any other host and runs guests through vfkit, the signed helper that drives Apple's Virtualization.framework. brew install vfkit is the one thing the agent cannot do for you—vfkit only works carrying Apple's virtualization entitlement, and an entitlement lives in a signature, so it comes from a signed distribution or not at all. Everything else the agent does itself: it installs as a LaunchAgent in the session you're already in, keeps its state in ~/.eitri/agent, and upgrades from the console like every other host. Releases ship a darwin_arm64 host bundle beside the Linux ones.

Hosts own their guest network. The subnet a host's guests live on is a fact about that host, and the host is the only thing that can observe it. So the direction reverses: a host tells the fleet which subnet its guests are on, a joining host proposes its own—the fleet's allocation is only a suggestion— and a Mac reports whatever subnet vmnet actually gave it. A host also refuses a guest subnet that contains its own uplink, naming both sides and the flag that fixes it, because that overlap takes out the very connection you'd use to fix it.

Published ports. SSH goes through the gate; anything else a guest serves needs a published port. You publish a VM's port on its host: the fleet binds a port on the host (30000–32767 when you leave the choice to it) and pipes it to the guest. The MCP tools speak it too, so an LLM that just built something in a VM can publish the port and hand back the address to dial. There is no authentication in front of a published port—whoever can reach the host on that port reaches the service—so publish what you're content to serve to everything on that network, and leave the rest to the gate.

Images, decoded in-process. The agent reads guest images itself: qcow2, vmdk, vhdx, vdi, parallels, vpc and asif are parsed in-process, gzip is decompressed sparsely as it lands, and an image that is already raw is renamed into place—there is no format to change. qemu-img goes with it. A Linux host needs KVM and nothing else.

Fixes. A VM says which SSH key eitri put in it—the key type, its fingerprint, its comment. A one-click create picks a default image its host's architecture can run, instead of one image for the whole fleet. A guest's address is judged on its own terms—does it name something reachable—rather than against an allocation the fleet made. A lost guest's report quotes the last thing its hypervisor said, instead of "lost" and nothing else. A backend signals only the processes it started, so a pid recycled across a host reboot is never someone else's process getting SIGKILL. And a host is asked whether it can run a guest at all before a create spends anything on a download.

Known limits.

v0.0.2

One fix, worth its own release. A guest's disk was handed to cloud-hypervisor without a declared format, and an autodetected raw image gets its sector 0 write-protected—so the first boot's partition grow only ever happened in the kernel's memory, and the guest died in initramfs the first time it was power-cycled. Disks are now declared raw and the partition table stays writable.

v0.0.1

The first release. eitri is a small cloud backed by your own hardware: one control-plane server—hosted at eitri.sh or run yourself—an agent on every Linux/KVM box you enroll, cloud-hypervisor microVMs, a web console, and SSH into guests through an identity-checking jump gate.

Fleet. Enroll any Linux/KVM host with a one-shot join command from the console. The agent reconciles each VM in its own worker, admits VMs against the host's real resources, fetches cloud-hypervisor and the guest firmware itself (sha-verified against the release), and upgrades itself from the console—running VMs survive agent restarts and upgrades.

VMs. UEFI guests boot any cloud-init disk image—the guest owns its kernel. Addressing is an embedded DHCP server with per-VM reservations. The console shows live host metrics, per-VM status and a browser serial console; tenant quotas bound what a tenant can create.

Sign-in and tenancy. The console signs in through OIDC—the bundled eitri-oidc issuer for a single box, or bring your own IdP (Google, Okta, Keycloak…). Every identity's first sign-in creates its own tenant; every API request, event stream, console session and audit row is tenant-scoped. CLI and automation authenticate with personal access tokens minted in the console.

SSH. Tenants register their own user CA—eitri never holds a user private key. eitri ssh self-signs a short-lived certificate, pins eitri's host CA, and jumps the gate to <tenant>.<vm>; certificates are revocable per serial. See ssh-access.md.

Hosted. Don't want to run the control plane? Sign in at console.eitri.sh with Google and join your own machines—the same server the tarball ships, run for you. Your hardware still serves every VM; the hosted plane only coordinates it. Self-hosting stays a first-class path.

Running it. eitri-server and eitri-oidc ship with hardened systemd units and run as dedicated non-root users; the agent's unit documents exactly why it runs as root. Server and issuer state live under /var/lib, config under /etc/eitri. The server speaks plain HTTP—front it with TLS if it leaves your LAN.

Platforms. Hosts: Linux amd64 and arm64 with KVM. Client CLI: Linux and macOS, amd64 and arm64.

Known limits.