Files
nix-config/modules/dev/qemu.org
T
phundrak ba018ef841 refactor: change to litterate config
Configuration is now held by the `.org` files. All `.nix` files are
tangled from the org-mode files.
2026-10-06 12:40:58 +02:00

2.5 KiB
Raw Blame History

QEMU

QEMU

On machines where I run virtual machines, I want virt-manager, libvirtd, and a few supporting pieces set up together. Here’s the skeleton of the nixos.qemu module.

{
  flake.modules.nixos.qemu = {
    config,
    lib,
    pkgs,
    ...
  }:
    with lib; let
      cfg = config.mySystem.dev.qemu;
    in {
      <<options>>
      config = {
        <<virt-manager>>
        <<libvirtd-group>>
        <<virtualisation>>
        <<packages>>
        <<firmware-tmpfiles>>
        <<binfmt>>
      };
    };
}

Declaring the Options

users lists which users get added to the libvirtd group, so they can manage VMs without needing root. By default, I add myself to this group.

options.mySystem.dev.qemu.users = mkOption {
  type = types.listOf types.str;
  default = ["phundrak"];
  example = ["user1" "user2"];
};

This option is then passed onto the standard NixOS option.

users.groups.libvirtd.members = cfg.users;

virt-manager

This pulls in the GUI I actually use to create and manage VMs.

programs.virt-manager.enable = true;

Virtualisation Backend

libvirtd is the daemon that actually runs and manages the VMs. SPICE USB redirection lets me pass a USB device straight through to a guest without unplugging it from the host first.

virtualisation = {
  libvirtd.enable = true;
  spiceUSBRedirection.enable = true;
};

Extra Packages

Besides qemu itself, quickemu lets me spin up a VM from a template in one command, and swtpm provides the software TPM that guests like Windows 11 insist on.

environment.systemPackages = with pkgs; [
  qemu
  quickemu
  swtpm
];

Firmware Lookup Path

virt-manager and friends expect to find UEFI firmware images under /var/lib/qemu/firmware, so I symlink QEMU’s own copy there instead of making every tool aware of the Nix store path.

systemd.tmpfiles.rules = ["L+ /var/lib/qemu/firmware - - - - ${pkgs.qemu}/share/qemu/firmware"];

ARM Emulation

This lets me run (and build) aarch64-linux binaries transparently through QEMU’s user-mode emulation, which comes in handy when working on the PineTab2 without needing actual ARM hardware on hand.

boot.binfmt.emulatedSystems = ["aarch64-linux"];