Architecture
Boot flow
How a microVM boots the universal initramfs, receives its environment over vsock, and starts the workload.
This page describes the current boot and execution path for workload microVMs.
It replaces the older per-rootfs init schemes (mvm-verity-init, mvm-oci-init,
busybox /init) with a single universal initramfs and a fail-closed
activation step over vsock. Every runner backend boots this contract —
Firecracker, libkrun, HVF, and QEMU (dev/test tier) all attach the universal
initramfs and deliver ActivateEnvironment over vsock. QEMU’s vhost-vsock
speaks real AF_VSOCK, so its channels ride a per-VM AF_VSOCK↔UNIX bridge
into the same per-port UNIX-socket convention the other backends expose
natively.
The universal initramfs
Section titled “The universal initramfs”The initramfs is a deterministic cargo artifact: the pinned agent
source is cross-compiled once (cargo zigbuild → musl, content-keyed
cache) and packed as an epoch-zero, stably-ordered cpio — no Nix on the
boot path. It is a small,
deterministic cpio that contains exactly one file:
/init— the staticmvm-guest-agentbinary.
It deliberately contains no /dev nodes (the build sandbox cannot create
device nodes). The guest creates them at boot by mounting devtmpfs.
The artifact is content-addressed and cached at
<MVM_HOME>/cache/initramfs/<version>/<arch>/ alongside initramfs.hash,
initramfs.size, and VERSION. On a cache miss the CLI seeds from the shared
default cache, builds it via nix build on Linux (through the builder-VM
boundary, never a host nix binary), or downloads a published release artifact
on macOS. Attaching the initramfs is non-fatal: a cold cache falls back to the
legacy boot path rather than failing the run.
Boot inputs and device layout
Section titled “Boot inputs and device layout”When the initramfs is attached, the backend boots:
- the workload kernel (
kernel_path), - the universal initramfs (
initrd_path), - the workload rootfs and its dm-verity sidecar,
- the runtime overlay and its dm-verity sidecar,
- any virtio-fs or virtio-blk volumes.
The block layout is fixed by the workload runner (verity sidecars are attached only for verity-sealed boots):
| Guest device | Content |
|---|---|
/dev/vda | rootfs data |
/dev/vdb | rootfs dm-verity hash tree (verity boots only) |
/dev/vdc | runtime overlay data |
/dev/vdd | runtime overlay dm-verity hash tree |
A block-less virtiofs-root dev boot attaches no disks at all; the root comes from a virtio-fs tag instead.
The kernel cmdline does not carry roothash tokens. The legacy
mvm.roothash=, mvm.data=, mvm.hash=, and mvm.runtime_*= tokens are gone;
the cmdline carries only the VMM console base plus
mvm.runtime_source_policy=… (and, when applicable, egress, verb-grant, and
user-volume tokens). The 2048-byte cmdline overflow guard still applies.
Guest PID 1: early setup, then a fail-closed gate
Section titled “Guest PID 1: early setup, then a fail-closed gate”mvm-guest-agent runs as /init (PID 1). Its startup sequence is:
- Mount
/procand/syswithMS_NOSUID | MS_NOEXEC | MS_NODEV. - Mount
devtmpfson/devwithMS_NOSUID(providing/dev/console,/dev/null, and friends). - Install a SIGCHLD handler so orphaned descendants are reaped immediately.
- Enter the normal vsock accept loop in the
Awaitingactivation state.
While in PID-1 initramfs mode, the dispatcher enforces a hard gate:
- Only
ActivateEnvironmentis accepted. - Every other operational verb is refused with
NotActivated. - If activation fails, the agent stays in
Failedand reports the reason on subsequent requests.
The guest exposes no operational RPC surface until the host activates it.
Host-side activation over vsock
Section titled “Host-side activation over vsock”After the VMM boots, the workload runner builds an ActivateEnvironment
message from the admitted launch config and sends it over the guest-agent
vsock port — for every boot that attached the universal initramfs, verified
or not. The message carries:
- Rootfs config — one of three shapes: a dm-verity block root (
/dev/vda/dev/vdb+ roothash, from the launch config or therootfs.roothashsidecar), an unverified plain-block root (/dev/vdaonly), or a virtio-fs root tag (mvmroot).
- Runtime overlay config —
/dev/vdc,/dev/vdd, and its roothash, when the boot carries an overlay. A rootfs-only boot sends no overlay. - Volumes —
DirSharevolumes translated to virtio-fs tags (uvol0,uvol1, …) with guest mountpoints and read-only flags.Diskvolumes are already attached as block devices, so they are not part of the message. - Optional verb-grant envelope — read from
<MVM_HOME>/vms/<name>/verb-grant.jsonwhen present.
The host requires an ActivateEnvironmentAck. Any error or unexpected response
fails the boot closed. A legacy per-rootfs verity initramfs (used when the
universal artifact is not cached yet) keeps its own PID 1 and is never sent
this verb.
Guest applies activation and pivots into the workload
Section titled “Guest applies activation and pivots into the workload”On receiving ActivateEnvironment, the guest:
- Mounts the root: the
rootdm-verity target from/dev/vda+/dev/vdbfor a sealed boot, the plain block device read-only for an unverified boot, or the virtio-fs tag for a block-less dev boot — staged at/mnt/root. - Mounts the runtime overlay read-only at
/mvm/runtimeinside the new root, when one was sent. - Mounts any virtio-fs volumes.
- Pivots the root filesystem to the mounted root.
- Drops privilege to the fixed workload UID/GID
901. - Flips the boot state to
Activatedand begins serving operational RPCs.
If a verb-grant envelope was included, the activation message must authenticate against the host-signer trust anchor before the agent accepts operational RPCs.
Execution after activation
Section titled “Execution after activation”Once activated, the guest is a normal workload VM:
- The runtime overlay at
/mvm/runtimeprovides the guest binaries. - The workload entrypoint runs under UID 901 inside the verified rootfs.
- Exit status, readiness, and entrypoint events stream back to the host over vsock.
- Egress still goes through the per-VM substitution endpoint (the sole egress gate, spawned before boot).
Warm-pool / standby note
Section titled “Warm-pool / standby note”Factory standby parents boot the same device model and cmdline shape as workloads, minus workload authority (no plan, no volumes, no broker, deny-all egress). They are captured before activation, so the warm-claim path with the universal initramfs is not armed yet; it is part of the HVF / warm-claim convergence work.
Future tiers and backends
Section titled “Future tiers and backends”The universal initramfs assumes a Linux guest kernel with virtio-blk / virtio-fs devices and a vsock channel. Tiers that don’t provide those get the model in adapted form — or honestly not at all:
- Wasm (
WasmBackend, ADR-024) — no Linux kernel and no initramfs: the workload is a WASI module under hostwasmtime, soActivateEnvironmentdoes not apply verbatim. Its implemented analog is the capability handshake: every run receives the same environment description adapted to WASI — the runtime-overlay guest binaries and each directory-share volume as preopened directories (read-only honored) at the same guest paths the other backends mount them, and policy/grant delivery as anactivation.json(overlay path, volume mountpoints, policy posture label, grant presence) preopened read-only at/run/mvmwithMVM_ACTIVATION_FILEin the module’s env. The WASI capability model is the gate: the module receives exactly the preopens, env, and host imports the plan admits and nothing else; there is no in-guest signature verification because the WASI host is the trust boundary. Kernel, verified-boot, block-volume, and console requests still fail closed. Per ADR-024 it stays opt-in, claim-free, and — if it ever executes real workloads — the engine runs in-guest, never as a host process dependency. - Docker / shared-kernel containers — removed by Plan 329. The ADR-034 dev tier has been deleted; mvm is microVM-only and a host with no usable hypervisor fails closed. The Apple Container backend remains available as an explicit opt-in on Apple Silicon, but it is a hardware-virtualized path (HVF with a container kernel), not a shared-kernel container.
- Apple Container — Apple’s prebuilt container kernel (a fetched binary
artifact, no toolchain) boots on mvm’s own HVF supervisor behind
--hypervisor apple-container(opt-in only, never auto-selected). The backend resolves the kernel from the local cache, sets it as the launch’s kernel image, and delegates the entire boot to the HVF workload runner: the same universal initramfs, the same agent-as-PID-1, and the sameActivateEnvironmentflow as every other backend — only the kernel differs. There is no Swift and no Virtualization.framework anywhere in the design (the earlier vminitd line was dropped: it is Swift with no prebuilt artifact). The kernel’s provenance is the artifact cache rather than an mvm build — recorded honestly in the backend’s security profile, seespecs/plans/271-apple-container-backend.md. - WHP (Windows Hypervisor Platform) — a future Windows-host backend. The
guest side is unchanged: the same kernel + universal initramfs boot and the
same
ActivateEnvironment. The work is entirely host-side — a WHPVmmDriver, virtio-blk/virtio-fs device model, and a vsock transport over Hyper-V sockets (AF_HYPERV) in place ofAF_VSOCK. dm-verity runs in the guest, so verified boot is host-agnostic and a WHP backend could target the same Tier 2 posture as HVF/libkrun once its egress gate lands. Until then, WSL2 with nested/dev/kvmis the supported Windows-adjacent path. - BrowserWasi (browser tier) — runs the workload as a WASI Preview 1 module
inside the browser’s own WebAssembly engine. There is no Linux kernel, no
initramfs, and no vsock; the capability handshake is implemented through
browser-native WASI imports and preopened directories. The guest workload
receives environment configuration through preopened directories (
/etc,/run/mvm) and a host-providedMVM_ACTIVATION_FILEenvironment variable. Network egress is mediated through the browser’sfetch()API via themvm:egresshost import, and file system isolation is enforced by the WASI preopen set. The tier is claim-free (no hardware isolation) and never auto-selected.
Security properties
Section titled “Security properties”- Fail-closed guest — no operational RPCs before a successful
ActivateEnvironment, on every boot that attaches the universal initramfs. - No roothash on the kernel cmdline — verity parameters travel over the
authenticated vsock channel instead of being visible in
/proc/cmdline. - Verified root where sealed — a verity boot only pivots into a rootfs that passed dm-verity; unverified dev-tier boots are mounted plainly and are exactly as trustworthy as the legacy path they replace.
- Least privilege after activation — the agent drops to UID 901 before running any workload code.