NixOS virtual machines#
One of the most important features of NixOS is the ability to configure the entire system declaratively, including packages to be installed, services to be run, as well as other settings and options.
NixOS configurations can be used to test and use NixOS using a virtual machine, independent of an installation on a “bare metal” computer.
Important
A NixOS configuration is a Nix language function following the NixOS module convention.
What will you learn?#
This tutorial serves as an introduction creating NixOS virtual machines. Virtual machines are a practical tool for debugging NixOS configurations.
What do you need?#
A working Nix installation on Linux, or NixOS, with a graphical environment
Basic knowledge of the Nix language
Starting from the default NixOS configuration#
In this tutorial you will use the default configuration that is shipped with NixOS.[1]
NixOS
On NixOS, use the nixos-generate-config
command to create a configuration file that contains some useful defaults and configuration suggestions.
By default, the configuration file is located at /etc/nixos/configuration.nix
.
To avoid overwriting this file you have to specify the output directory.
Create a NixOS configuration in your working directory:
nixos-generate-config --dir ./
In the working directory you will then find two files:
hardware-configuration.nix
is specific to the hardwarenix-generate-config
is being run on. You can ignore that file for this tutorial because it has no effect inside a virtual machine.configuration.nix
contains various suggestions and comments for the initial setup of a desktop computer.
The default NixOS configuration without comments is:
1{ config, pkgs, ... }:
2{
3 imports = [ ./hardware-configuration.nix ];
4
5 boot.loader.systemd-boot.enable = true;
6 boot.loader.efi.canTouchEfiVariables = true;
7
8 services.xserver.enable = true;
9
10 services.xserver.displayManager.gdm.enable = true;
11 services.xserver.desktopManager.gnome.enable = true;
12
13 system.stateVersion = "22.05";
14}
To be able to log in add the following lines to the returned attribute set:
1 users.users.alice = {
2 isNormalUser = true;
3 extraGroups = [ "wheel" ];
4 packages = with pkgs; [
5 firefox
6 tree
7 ];
8 };
NixOS
On NixOS your configuration generated with nix-generate-config
contains this user configuration commented out.
Additionally, you need to specify a password for this user.
For the purpose of demonstration only, you specify an insecure, plain text password by adding the initialPassword
option to the user configuration:
1initialPassword = "testpw";
Warning
Do not use plain text passwords outside of this example unless you know what you are doing. See initialHashedPassword
or ssh.authorizedKeys
for more secure alternatives.
This tutorial focuses on testing NixOS configurations on a virtual machine.
Therefore you will remove the reference to hardware-configuration.nix
:
- imports = [ ./hardware-configuration.nix ];
The complete configuration.nix
file now looks like this:
1{ config, pkgs, ... }:
2{
3 boot.loader.systemd-boot.enable = true;
4 boot.loader.efi.canTouchEfiVariables = true;
5
6 services.xserver.enable = true;
7
8 services.xserver.displayManager.gdm.enable = true;
9 services.xserver.desktopManager.gnome.enable = true;
10
11 users.users.alice = {
12 isNormalUser = true;
13 extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
14 packages = with pkgs; [
15 firefox
16 tree
17 ];
18 initialPassword = "testpw";
19 };
20
21 system.stateVersion = "22.11";
22}
Creating a QEMU based virtual machine from a NixOS configuration#
A NixOS virtual machine is created with the nix-build
command:
nix-build '<nixpkgs/nixos>' -A vm \
-I nixpkgs=channel:nixos-22.11 \
-I nixos-config=./configuration.nix
This command builds the attribute vm
from the nixos-22.11
release of NixOS, using the NixOS configuration as specified in the relative path.
Detailed explanation
The positional argument to
nix-build
is a path to the derivation to be built. That path can be obtained from a Nix expression that evaluates to a derivation.The virtual machine build helper is defined in NixOS, which is part of the
nixpkgs
repository. Therefore we use the lookup path<nixpkgs/nixos>
.The
-A
option specifies the attribute to pick from the provided Nix expression<nixpkgs/nixos>
.To build the virtual machine, we choose the
vm
attribute as defined innixos/default.nix
.The
-I
option prepends entries to the search path.Here we set
nixpkgs
to refer to a specific version of Nixpkgs and setnix-config
to theconfiguration.nix
file in the current directory.
NixOS
On NixOS the $NIX_PATH
environment variable is usually set up automatically, and there is also a convenience command for building virtual machines.
You can use the current version of nixpkgs
to build the virtual machine like this:
nixos-rebuild build-vm -I nixos-config=./configuration.nix
Running the virtual machine#
The previous command created a link with the name result
in the working directory.
It links to the directory that contains the virtual machine.
ls -R ./result
result:
bin system
result/bin:
run-nixos-vm
Run the virtual machine:
./result/bin/run-nixos-vm
This command opens a QEMU window that shows the boot process of the virtual machine which ends at the GDM login screen.
Log in as alice
with the password testpw
.
Running the virtual machine will create a nixos.qcow2
file in the current directory.
This disk image file contains the dynamic state of the virtual machine.
It can interfere with debugging as it keeps the state of previous runs, for example the user password.
Delete this file when you change the configuration:
rm nixos.qcow2