Override QEMU options in runInLinuxVM

I have a flake file that builds disk image using make-zfs-image.nix. However, my system doesn’t have KVM module.

How can I override QEMU options in make-zfs-image.nix to run with tcg accelerator, instead of KVM?

Even after trying to adapt dozens of code examples online, I ran out of ideas how to accomplish that. Any help is much appreciated.

==================================================
System
Apple Silicon M1 running QEMU VM with Ubuntu aarch64 guest.
What I’ve tried

  • Confirmed that nix QEMU VM can run on my system. E.g., if I build any VM, then I can run it with accel=tcg like in following example:
    ./result/bin/run-nixos-vm -cpu max -smp 8 -machine accel=tcg,gic-version=max -vga std -m 800M
  • Used various versions of an overlay with no success (see below)

Here’s how I tried to override QEMU_OPTS:

{
  description = "Example";
  inputs = {
    nixpkgs.url = "flake:nixpkgs";
  };

  outputs = { self, nixpkgs }@inputs: {
    diskImages = {
      test = let
        overlay1 = (final: prev:
          let
            runInLinuxVMNoKVM = drv:
              final.lib.overrideDerivation (final.vmTools.runInLinuxVM drv)
              (_: {
                requiredSystemFeatures = [ ];
                QEMU_OPTS =
                  "-cpu max -smp 8 -machine accel=tcg,gic-version=max -m 800M";
              });
            modifiedVmTools = prev.vmTools // {
              runInLinuxVM = runInLinuxVMNoKVM;
            };
          in { vmTools = modifiedVmTools; });
        overlay2 = (final: prev: rec {
          vmTools = prev.vmTools // {
            runInLinuxVM = drv:
              final.lib.overrideDerivations (final.vmTools.runInLinuxVM drv)
              (_: {
                requiredSystemFeatures = [ "xxxx" ];
                QEMU_OPTS =
                  "-cpu max -smp 8 -machine accel=tcg,gic-version=max -m 800M";
              });
          };
        });
        overlay3 = (final: prev: rec {
          vmTools.runInLinuxVM = prev.vmTools.runInLinuxVM.overrideAttrs
            (oldAttrs: rec {
              QEMU_OPTS =
                "-cpu max -smp 8 -machine accel=tcg,gic-version=max -m 800M";
            });
        });
        system = "aarch64-linux";

        pkgs = import nixpkgs {
          inherit system;
          overlays = [ overlay1 ]; # I tried different overlays here
          virtualization.libvirtd = { enableKVM = false; };
        };
      in import "${nixpkgs}/nixos/lib/make-zfs-image.nix" {
        pkgs = pkgs;
        lib = pkgs.lib;
        format = "qcow2";
        config = ((import ./systems/vm) inputs).config;
        configFile = pkgs.writeText "configuration.nix" ''
          {

          }
        '';
      };
    };
  };
}

With overlay 1,2 I get:

~/x/nix [master] λ nix build '.#diskImages.test'
building '/nix/store/acv3lzw9j7igqq890jb10xyhcahs3qbg-nixos-disk-image.drv'...
builder for '/nix/store/acv3lzw9j7igqq890jb10xyhcahs3qbg-nixos-disk-image.drv' failed with exit code 1; last 10 log lines:
  Could not access KVM kernel module: No such file or directory
  qemu-system-aarch64: failed to initialize kvm: No such file or directory
error: build of '/nix/store/acv3lzw9j7igqq890jb10xyhcahs3qbg-nixos-disk-image.drv' failed

Overlay 3

~/x/nix [master] λ nix build '.#diskImages.test'
error: attribute 'override' missing
       at /nix/store/y4k5zwrlz0qv1r32jsgfvykb9x31n4kj-source/nixos/lib/make-zfs-image.nix:241:5:

          240|   image = (
          241|     pkgs.vmTools.override {
             |     ^
          242|       rootModules =
(use '--show-trace' to show detailed location information)

Just in case anyone else runs into the same snag. Overriding QEMU parameters requires a couple of nasty hacks, as described here. Hope it helps someone.

1 Like