Guides
WSL2 notes for mvm
WSL2 workload-host notes for mvm. WSL2 with nested KVM is supported for the libkrun-backed workload path.
This page documents the supported Windows-adjacent runtime path: run mvm
inside a WSL2 distro that exposes nested /dev/kvm, install libkrun in the
distro, and keep both the repo and runtime state on the WSL ext4 filesystem.
Native Windows host support is still tracked separately in
mvm#428.
Why WSL2 for mvm
Section titled “Why WSL2 for mvm”WSL2 is a real Linux kernel running under Hyper-V. In this slice, mvm treats it
as a supported libkrun-backed workload host when the distro exposes
/dev/kvm. From inside a capable WSL2 distro:
/dev/kvmmust be available. When it is missing, the supported WSL2 workload path is unavailable.- Filesystem is real Linux ext4. APFS-style copy-on-write isn’t here yet (Sprint 47 Plan D ships APFS CoW for macOS; WSL2’s ext4 will fall back to byte-copy in
mvm-runtime::vm::cow::reflink_or_copy), but everything functionally works. - Networking is bridged through Hyper-V’s vmswitch. Port forwarding from Windows host to a WSL2 distro is automatic for
127.0.0.1binds; mvm guests behind the WSL2 distro need an additional hop, covered below.
The cost is one nested VM hop: workload runs inside a microVM, inside WSL2, inside Hyper-V on the Windows host. This is a supported workload runtime shape, not a promise that native Windows or WSL2 builder/dev flows are feature-complete.
The install quickstart covers wsl --install + cargo install. Two follow-up steps that matter for mvm specifically:
Confirm nested KVM works
Section titled “Confirm nested KVM works”ls -l /dev/kvmShould show a character device. If /dev/kvm is missing, WSL2 didn’t pick up nested virt. Two fixes:
- Update Windows + WSL to current versions:
Terminal window wsl --update - Confirm BIOS settings: VT-x / AMD-V enabled, Hyper-V allowed.
If mvmctl doctor still reports KVM unavailable, see the No /dev/kvm available entry.
Keep the repo and state on ext4
Section titled “Keep the repo and state on ext4”The supported path is:
- repo/worktree under the WSL distro filesystem, for example
~/work/... - runtime state under the default
~/.mvmor another ext4-backedMVM_HOME
Do not run the workload path from /mnt/c/... or point MVM_HOME at a
DrvFs mount. mvmctl doctor refuses that shape because it is too flaky.
Allocate WSL2 resources
Section titled “Allocate WSL2 resources”WSL2 starts with a default of 50% of host RAM and all CPUs. mvm guests run inside this budget. For a comfortable dev machine:
%USERPROFILE%\.wslconfig:
[wsl2]memory=12GBprocessors=8Then restart WSL: wsl --shutdown and reopen the Ubuntu shell.
Declared ingress (Windows host ↔ mvm guest)
Section titled “Declared ingress (Windows host ↔ mvm guest)”mvm guests have no workload NIC. To expose a guest service to a Windows-side browser, declare its FlowMux ingress mapping before boot:
- Boot a named machine that serves on port 8080:
Terminal window mvmctl machine run --name my-vm --manifest . --port 8080:8080 - WSL2’s automatic localhost forwarding (documented by Microsoft) makes
localhost:8080on Windows reach the WSL2 distro’s loopback. Openhttp://localhost:8080in a Windows browser and you’re hitting the admitted FlowMux listener.
If localhost forwarding isn’t working (some corporate VPN clients break it), fall back to the WSL2 distro’s IP:
hostname -I # inside WSL2 — gives the distro's IP on the Hyper-V vmswitchThen http://<that-ip>:8080 from Windows.
File sharing
Section titled “File sharing”/mnt/c/ (and similar) inside WSL2 maps to Windows drives. Don’t run mvm
from /mnt/c/ — the cross-fs perf is brutal and the runtime/socket path
shape is not part of the supported WSL2 workload surface. Keep mvm work inside
the WSL2 ext4 filesystem (e.g. ~/work/...).
If you need to read source from a Windows directory, do it explicitly with cp rather than running cargo build against a /mnt/c/ path.
Live smoke
Section titled “Live smoke”For an opt-in proof on a real WSL2 host, run:
sh scripts/run-wsl2-libkrun-smoke.shUse a real Windows host running WSL2 for this proof, for example:
- Windows 11 with WSL2 and nested
/dev/kvmexposed inside the distro; - Windows Server with WSL2 enabled and the same nested-KVM shape.
Do not treat the following as equivalent proof for this guide:
- macOS integration layers such as OrbStack;
- plain Linux VMs that are not actually WSL2;
- Hetzner Cloud or other hosted VMs that do not expose the required nested-virt shape.
The wrapper checks that you are inside WSL2, confirms /dev/kvm exists, and
refuses DrvFs-backed repo/state paths. It then:
- runs the gated libkrun backend lifecycle smoke;
- scaffolds and builds a temporary HTTP preset manifest;
- proves transient
run --json --receipt; - boots a persistent libkrun-backed machine and waits for guest-agent reachability;
- verifies
machine exec,--allow-hostegress, declared FlowMux ingress, and clean stop.
Future Backend Work
Section titled “Future Backend Work”Two Windows paths remain plausible future work:
- native Windows backend/builder work, distinct from this WSL2 slice;
- Hyper-V managed Linux builder/backend VM, with its own lifecycle and trust model.
Neither path is part of the supported local platform matrix today.
Tracking issue: Future work: Windows host support via Windows Hypervisor Platform.
See also
Section titled “See also”- Install on Windows
- Matryoshka model — what each isolation tier promises
- Windows troubleshooting
- WSL2 documentation