QEMU (Quick Emulator) is an open-source machine emulator and virtualizer. When paired with KVM, guest CPU instructions execute directly on the physical CPU at near-native speed; QEMU’s job is device emulation — disk, display, USB, and network.
Without KVM, QEMU can also run in pure software emulation mode (much slower), translating guest instructions on the fly. Most production use pairs QEMU with KVM.
Networking via TAP
For VM networking, QEMU runs as a host userspace process and acts as the bridge between the guest and the host kernel:
- Opens
/dev/net/tunand requests a TAP interface (e.g.vm-<name>) — this gives QEMU a file descriptor into the host kernel’s network stack - Exposes a virtio-net PCI device to the guest OS — the guest sees this as a normal Ethernet card
QEMU then runs a forwarding loop that connects those two ends:
// send path (guest → host)
frame = read from virtio-net queue // guest just sent an Ethernet frame
write(tap_fd, frame) // inject it into the host kernel network stack
// receive path (host → guest)
frame = read(tap_fd) // host kernel delivered an Ethernet frame to vm-<name>
write to virtio-net queue // hand it to the guest's network stack
This loop is what “shuttles” means: QEMU sits in the middle, continuously reading from one side and writing to the other. It is not a kernel feature — it is a tight read/write loop in QEMU’s own code. Without QEMU running, the two ends (virtio-net and TAP) are not connected to each other.
The host-side TAP interface is then attached to a bridge (e.g. microvm-br) for routing to the physical NIC. See Linux Networking for the full diagram and /dev/net/tun explanation.
microvm.nix — QEMU vs Firecracker
microvm.nix is a NixOS module for running lightweight VMs as systemd services. It supports multiple VMM backends, of which QEMU and Firecracker are the two main ones. They are alternatives — you pick one per VM.
| QEMU | Firecracker | |
|---|---|---|
| Made by | open-source community | AWS |
| Device support | Rich: many NICs, GPUs, USB, arbitrary architectures | Minimal: virtio-net, virtio-blk, serial only |
| Attack surface | Large (emulates many devices) | Small (seccomp-filtered, minimal device set) |
| Startup time | ~500 ms | ~125 ms |
| Typical use | Development VMs, desktop virtualisation | Production serverless (Lambda, Fargate), CI runners |
Why two? QEMU’s rich device emulation makes it flexible for development — you can attach USB, emulate different CPUs, use OVMF UEFI, etc. Firecracker intentionally supports almost nothing: it exists purely for security and density in multi-tenant environments where you don’t trust the workload and need to start thousands of VMs per second.
microvm.nix wraps both so you can use the same NixOS VM definition and just switch the backend — the NixOS configuration for the guest is identical regardless of whether QEMU or Firecracker runs it.
Each VM still gets a TAP interface named vm-<name> regardless of backend. If a microVM crash-loops, see NetworkManager for the NM dispatcher noise this causes.