Atomic Upgrades in NixOS: How System Generations Make Rollbacks a Breeze
NixOS’s system generations turn upgrades into a risk‑free experiment. Learn how atomic rollbacks, disk‑space trade‑offs, and mutable‑state limits shape a safe upgrade workflow, complete with a step‑by‑step example.
12 Jul 2025, 06:04 UTC

Why Upgrade Risk Matters in NixOS
When you tweak a Linux distribution, you’re usually juggling two concerns: does the new package work? and can I undo it if something breaks? NixOS turns the second question into a built‑in feature with its system generations and atomic rollback. The result is a low‑risk upgrade path that is especially valuable for servers and developers who need to experiment safely.
What Is a Generation?
Every time you run nixos-rebuild switch, NixOS takes the declarative configuration in /etc/nixos/configuration.nix (and any imported modules) and builds a complete system closure in the read‑only Nix store. It then creates a symlinked directory called /nix/var/nixos/GENERATIONS/n that points to the new store path. The boot loader (systemd‑boot, GRUB, etc.) automatically adds an entry for this generation, so you can boot into it directly from the menu.
Because the closure is immutable and reproducible, the same configuration will always produce the same result, which is the bedrock of the rollback guarantee.
Rolling Back in One Command
If the new generation fails—say a service stops or a kernel update breaks a driver—you can restore the previous stable state in two ways:
- Boot‑loader selection: Reboot and pick the older generation from the boot menu. The system will start exactly as it did before the upgrade.
- Command‑line rollback: While the new generation is active, run
sudo nixos-rebuild switch --rollback. NixOS automatically resolves the most recent successful generation and switches to it, updating the boot loader symlink in the process.
Both methods are atomic: the switch happens in a single transaction, and you never end up in a partially upgraded state.
Disk Space: The Cost of Safety
Every generation consumes space in /nix/store and the /nix/var/nixos/GENERATIONS directory. A typical system might accumulate several gigabytes after a month of frequent upgrades. To keep the store lean, run:
sudo nix-collect-garbage -d
This command deletes all store paths that are not needed by any active generation, but it preserves the most recent ones. You can also set nix.gc.dates and nix.gc.options in configuration.nix to automate cleanup.
What Rollback Does Not Restore
The atomicity of rollback applies to the system closure—packages, kernel, system services, and configuration files under /etc. It does not touch mutable state such as:
- Data in
/var(e.g., database files, log directories) - User home directories (
/home) - External storage or network mounts
Consequently, if a broken upgrade corrupts a database, rolling back the system will not recover the lost data. Backups of /var and other stateful directories remain essential.
Worked Example: A Broken Service and a Clean Recovery
Assume you want to upgrade the nginx package to a newer version. Follow these steps on a test VM:
- Record the current generation:
nixos-rebuild list-generations # Note the number of the latest generation, e.g., 42 - Update the configuration:
sudo editor /etc/nixos/configuration.nix # Change nginx version or enable a new module - Apply the upgrade:
sudo nixos-rebuild switch - Verify the new generation:
nixos-rebuild list-generations # A new generation (e.g., 43) should appear - Simulate a failure: Stop the service deliberately.
sudo systemctl stop nginx - Attempt to start it:
sudo systemctl start nginx # Expect failure (e.g., “Failed to start nginx.service”) - Rollback:
sudo nixos-rebuild switch --rollback - Confirm restoration:
systemctl status nginx # Should show “active (running)” and the old configuration
Throughout this sequence, the system’s binary packages and configuration files revert to the previous state, but any logs or uploaded files in /var/log/nginx remain untouched.
Actionable Takeaways
- Always run
nixos-rebuild switchto create a new generation; it’s the safest upgrade path. - Use
--rollbackor the boot menu to recover quickly if a service fails. - Regularly prune old generations with
nix-collect-garbage -dto avoid disk bloat. - Back up mutable state separately; rollback does not restore databases or user data.
- Consider using
nixos-rebuild testfor experimental changes that you don’t want to add to the boot menu yet.
With these practices, NixOS turns every upgrade into a low‑risk experiment rather than a potential outage. The atomic nature of generations and rollback lets you focus on feature work instead of firefighting.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.