OFFSET偏移
← All articlesOFFSET / FIELD NOTESNO. 069

Validating NixOS configuration with QEMU

From a minimal configuration to GNOME and Sway, distinguish VM declarations from persistent disk state.

English translation · Code and commands follow the Chinese original.

IN THESE READING PATHSNixOS virtualization and deployment ↗
About 4 min readStart reading

Version scope: the following examples retain the tutorial's NixOS 24.05 context; that release is no longer maintained. Real projects should use a supported release, lock a nixpkgs revision, and check the corresponding options. system.stateVersion defines a compatibility baseline and should not be changed mechanically during upgrades. The commands in this article are teaching examples and were not run or verified on the target system.

Translated from nix.dev: NixOS virtual machines

This chapter explains how to create and manage NixOS virtual machines, an excellent way to test configurations and learn NixOS.

Learning Objectives#

  • Create a basic NixOS virtual-machine configuration
  • Run a virtual machine with QEMU
  • Configure a graphical interface (GNOME/Sway)
  • Understand virtual-machine parameters

Prerequisites#

  • A Linux system with virtualization support
  • Nix installed (installation instructions at nix.dev/install-nix)
  • Basic knowledge of the Nix language

1. Basic Configuration#

Create a configuration.nix file:

{ config, pkgs, ... }:
{
  # 引导加载器配置
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # 创建用户
  users.users.alice = {
    isNormalUser = true;
    extraGroups = [ "wheel" ];  # 启用 sudo
    initialPassword = "<VM_TEST_PASSWORD>";   # 初始密码(仅演示用)
  };

  # 安装示例软件包
  environment.systemPackages = with pkgs; [
    cowsay
    lolcat
  ];

  # 系统版本
  system.stateVersion = "24.05";
}

2. Build the Virtual Machine#

Build the virtual machine with nix-build:

nix-build '<nixpkgs/nixos>' -A vm \
  -I nixpkgs=channel:nixos-24.05 \
  -I nixos-config=./configuration.nix

Command breakdown:

  • <nixpkgs/nixos>: the NixOS entry-point file
  • -A vm: build the vm attribute
  • -I nixpkgs=channel:nixos-24.05: use the NixOS 24.05 channel
  • -I nixos-config=./configuration.nix: specify your configuration file

3. Run the Virtual Machine#

After the build, a result symlink appears in the current directory:

# 查看生成的文件
ls -R ./result

# 运行虚拟机(无图形界面)
QEMU_KERNEL_PARAMS=console=ttyS0 ./result/bin/run-nixos-vm -nographic

Note: Run reset after exiting the VM to restore terminal settings. A plaintext initialPassword is suitable only for disposable, isolated test VMs. Production systems should use a password file or a verified SSH public-key configuration.

Log in:

  • Username: alice
  • Password: the value you substituted for <VM_TEST_PASSWORD> in the configuration

Test the installed software:

cowsay hello | lolcat

Exit the virtual machine:

sudo poweroff

Clear Virtual-Machine State

Running the VM creates a nixos.qcow2 disk image in the directory to hold its state. After changing the configuration, if you want to clear old passwords and runtime state, first stop the VM and confirm there is no data you need to retain, then delete its disk:

rm nixos.qcow2

4. A Graphical Virtual Machine (GNOME)#

To run the GNOME desktop environment in the VM, modify the configuration:

{ config, pkgs, ... }:
{
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # 启用 X11
  services.xserver.enable = true;

  # 启用 GDM 和 GNOME
  services.xserver.displayManager.gdm.enable = true;
  services.xserver.desktopManager.gnome.enable = true;

  users.users.alice = {
    isNormalUser = true;
    extraGroups = [ "wheel" ];
    initialPassword = "<VM_TEST_PASSWORD>";
  };

  system.stateVersion = "24.05";
}

After modifying the configuration, rerun the VM build command above, then launch it without the -nographic argument:

./result/bin/run-nixos-vm

Use a Predefined Installation-Image Configuration

NixOS provides predefined graphical installation-image configurations:

nix-shell -I nixpkgs=channel:nixos-24.05 -p "$(cat <<EOF
  let
    pkgs = import <nixpkgs> { config = {}; overlays = []; };
    iso-config = pkgs.path + /nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix;
    nixos = pkgs.nixos iso-config;
  in nixos.config.system.build.nixos-generate-config
EOF
)"

nixos-generate-config --dir ./

5. A Wayland Desktop (Sway)#

To run Sway, a Wayland window manager:

{ config, pkgs, ... }:
{
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  services.xserver.enable = true;
  services.xserver.displayManager.gdm.enable = true;

  # 启用 Sway
  programs.sway.enable = true;

  users.users.alice = {
    isNormalUser = true;
    extraGroups = [ "wheel" ];
    initialPassword = "<VM_TEST_PASSWORD>";
  };

  system.stateVersion = "24.05";
}

Note: Running Wayland in a virtual machine may require a specific QEMU display driver:

./result/bin/run-nixos-vm -device virtio-vga

Declare QEMU Options in the Configuration

{ config, pkgs, ... }:
{
  # ... 前面的配置 ...

  # 导入 QEMU 虚拟机模块
  imports = [ <nixpkgs/nixos/modules/virtualisation/qemu-vm.nix> ];

  # 配置 QEMU 选项
  virtualisation.qemu.options = [
    "-device virtio-vga"
  ];

  system.stateVersion = "24.05";
}

Virtual-Machine Configuration Options#

View all available QEMU configuration options:

Practical Tips#

Quickly Restart the Virtual Machine

# 在虚拟机内执行
sudo reboot

Force-Stop the Virtual Machine

# 从另一个终端确认该测试 VM 的 PID
pgrep -af qemu
# 只终止已确认的测试 VM;替换占位符后执行
kill <TEST_VM_PID>

View Virtual-Machine Logs

QEMU_KERNEL_PARAMS=console=ttyS0 ./result/bin/run-nixos-vm -nographic 2>&1 | tee vm.log

Next Steps#


Reference Resources#


References & further reading

  1. nix.dev virtual-machine tutorial ↗
  2. QEMU system emulator documentation ↗

Adapted from technical notes. Examples use generic names.

Continue along a reading path

NixOS virtualization and deployment

  1. 01Validating NixOS configuration with QEMU
  2. 02Building a bootable NixOS ISO
  3. 03Building and running container images with dockerTools
  4. 04Deploying NixOS over SSH
  5. 05Dividing deployment responsibilities between Terraform and NixOS
  6. 06Designing layered desktop and development environments
CONTINUE READING / NEXT ARTICLEBuilding a bootable NixOS ISO

Customize software, graphical desktops, and bootable images through installation-media modules.