Magic Deployments with nixos-rebuild
One of the things you learn after installing NixOS for the first time is that
all these tasks are basically the same from a tooling perspective:
Adding/removing a package, massively changing the system configuration, or
simply updating it.
After changing the configuration and/or the inputs, you run nixos-rebuild
and the system is deployed.
If the configuration turns out to be bad - it can simply be rolled back!
But how does this tool work and what other cool features does it have?
The Nix & NixOS 101 class teaches how to install NixOS
and how to experiment with NixOS configurations using nixos-rebuild
.
As this class is already packed with so many other useful things like how to
write NixOS modules and NixOS integration tests, we are only scratching the
surface of what nixos-rebuild
can do!
What is nixos-rebuild
?
nixos-rebuild
is the standard tool for altering the system configuration of
an installed NixOS system.
The typical steps are, as
described in the NixOS documentation:
- Change NixOS configuration
- by changing the configuration in your
flake.nix
file - by updating the inputs with
nix flake update
- by changing the configuration in your
- Run
sudo nixos-rebuild switch
That’s it. You might want to reboot the system if the kernel was updated.
How Does It Look Like?
Let’s perform a full system upgrade:
$ nix flake update --commit-lock-file
warning: updating lock file '/home/tfc/src/nixos-configs/flake.lock':
• Updated input 'nixpkgs':
'github:NixOS/nixpkgs/ac1acba43b2f9db073943ff5ed883ce7e8a40a2c' (2023-07-23)
→ 'github:NixOS/nixpkgs/f3fbbc36b4e179a5985b9ab12624e9dfe7989341' (2023-07-26)
warning: committed new revision 'ba119606b5ca47f43b8fa338bd02fe37aa6d405f'
The
--commit-lock-file
argument is optional but handy if the configuration is stored in agit
repository. If you are going to commit the lock file anyway,nix flake update
can commit it for you.
After an update, the system typically needs to be rebuilt even without other configuration changes:
$ sudo nixos-rebuild switch
building the system configuration...
stopping the following units: accounts-daemon.service, cpufreq.service, systemd-udevd-control.socket, systemd-udevd-kernel.socket, systemd-udevd.service
NOT restarting the following changed units: display-manager.service, libvirt-guests.service, systemd-fsck@dev-disk-by\x2duuid-091D\x2d4B27.service
activating the configuration...
warning: not applying GID change of group ‘localtimed’ (990 -> 325) in /etc/group
warning: not applying UID change of user ‘localtimed’ (993 -> 325) in /etc/passwd
setting up /etc...
reloading user units for tfc...
setting up tmpfiles
reloading the following units: dbus.service
restarting the following units: home-manager-tfc.service, nix-daemon.service, polkit.service, sshd.service
starting the following units: accounts-daemon.service, cpufreq.service, systemd-udevd-control.socket, systemd-udevd-kernel.socket
the following new units were started: libvirtd.service
If the new configuration is not good for some reason, it can be rolled back:
$ sudo nixos-rebuild switch --rollback
[sudo] password for tfc:
switching profile from version 359 to 358
stopping the following units: accounts-daemon.service, cpufreq.service, systemd-udevd-control.socket, systemd-udevd-kernel.socket, systemd-udevd.service
NOT restarting the following changed units: display-manager.service, libvirt-guests.service, systemd-fsck@dev-disk-by\x2duuid-091D\x2d4B27.service
activating the configuration...
warning: not applying GID change of group ‘localtimed’ (990 -> 325) in /etc/group
warning: not applying UID change of user ‘localtimed’ (993 -> 325) in /etc/passwd
setting up /etc...
reloading user units for tfc...
setting up tmpfiles
reloading the following units: dbus.service
restarting the following units: home-manager-tfc.service, nix-daemon.service, polkit.service, sshd.service
starting the following units: accounts-daemon.service, cpufreq.service, systemd-udevd-control.socket, systemd-udevd-kernel.socket
the following new units were started: libvirtd.service
The activation of a new/old configuration takes only seconds depending on how many services need to be restarted.
What Other Features Does nixos-rebuild
Provide?
nixos-rebuild
provides functionality on two different axes:
- Command Targets
- Just evaluate the NixOS configuration
- Evaluate & build
- Evaluate, build, and activate the new NixOS config temporarily or permanently
- Dry-run activation to see the impact on the system
- Build and run a VM for testing
- Locality
- Local NixOS rebuilds
- Remote deployment to other hosts
- Remote building of the new NixOS configuration
The remote building capabilities of nixos-rebuild
are very interesting, too.
We will have a look at them in
the next blog article.
So what are the command targets? These are the most interesting ones for day-to-day use:
nixos-rebuild ... | Functionality |
---|---|
switch | Builds and activates the system configuration with immediate effect. In addition to that, it installs the configuration in the bootloader. |
test | Like switch , but does not update the bootloader list. |
boot | Builds the config and updates the bootloader list without activating the system immediately. |
dry-run | Only evaluates the config without building it. |
dry-activate | Builds the config and print which changes would be performed on the current system during activation. |
build-vm | Builds the config and generates a script that starts this configuration as a VM on your local system. |
The build-vm
part is interesting - let’s try it out:
$ nixos-rebuild build-vm
building the system configuration...
Done. The virtual machine can be started by running /nix/store/yscmmshi2q0dmr6xcfdnhz3829sd5lqz-nixos-vm/bin/run-jongepad-vm
$ ./result/bin/run-jongepad-vm
Disk image do not exist, creating the virtualisation disk image...
Formatting '/home/tfc/src/nixos-configs/jongepad.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
Virtualisation disk image created.
Running the script starts the VM and after boot, it shows the same login manager as my laptop does:
Of course, we can’t really log in without setting a password first, because the user passwords are not part of the NixOS configuration. During the installation of a local NixOS system, we set them imperatively. Remote system deploys typically use SSH key authorization instead of passwords.
Other Interesting Parameters
--rollback
With every activation, the path /nix/var/nix/profiles/system
is set to the new
configuration.
For every activated configuration, nix adds another symlink
/nix/var/nix/profiles/system-XYZ-link
to the profiles folder, where XYZ
is
the number of the current system.
Each of these systems is considered another NixOS system generation.
When --rollback
is used in combination with switch
, test
, or boot
,
nixos-rebuild
does not build and activate a new system version but reactivate
the last one.
--flake
Adding --flake path/to/flake/repo#systemName
to the command line tells
nixos-rebuild
to use the flake at path path/to/flake/repo
and use the
system configuration with the name systemName
.
If the #systemName
part is omitted, nixos-rebuild
tries to deduce it from
the local hostname.
The --flake
parameter can be omitted if the system has a
/etc/nixos/flake.nix
flake file.
The system name is also automatically deduced from the host name in this case.
--fast
/ --no-build-nix
To make sure that the latest version of nix
is used for the deployment,
nixos-rebuild
obtains the latest pkgs.nixUnstable
version.
Using this flag can accelerate the process by trusting that the currently
installed version is compatible.
MacOS Users also need to use this flag when remote-deploying to a NixOS system from their Mac.
--profile-name
It is possible to create system configurations with specific profile names, like for example “maintenance”, or “lanparty”. These are installed into the bootloader next to the default system profile and can be selectively booted when needed.
Summary & Outlook
Installing, removing, upgrading, and configuring packages and system services is painless on NixOS: Instead of tampering with the system state by imperatively installing packages and manipulating service configurations, we have a central NixOS configuration that can be versioned and describes it all.
Given any NixOS configuration, we can build
and switch
to this configuration
with a single command using nixos-rebuild
.
If the new config turns out to be bad, we can simply --rollback
any time, or
boot into the last system generation!
Even before doing that, we can dry-activate
or build-vm
to test if our
config makes sense even before deploying it to a real system.
The next article shows how to use nixos-rebuild
to remotely deploy NixOS
configurations
on target machines via network.
In addition to that, we will see how to remote build configurations on other
hosts via network, may that be for performance reasons or cross-compilation.