How NixOS’s Atomic Generations Make Zero‑Downtime Upgrades a Reality
Upgrade a production NixOS server safely by leveraging atomic generations. Learn the step‑by‑step process, a useful example, and the trade‑offs that come with NixOS's declarative system.
18 Sept 2025, 07:53 UTC

Problem: Upgrading a Production Server with Confidence
When a web‑application runs on a server that can’t afford downtime, any update that breaks a service can be catastrophic. Traditional package managers install a new binary, overwrite the old one, and if something goes wrong the system may end up in an inconsistent state. NixOS tackles this by treating the entire OS as a declarative Nix expression. The result is a set of generations – snapshots of the system state – that can be switched atomically at boot time.
Thesis: Use NixOS Generations to Upgrade Safely
The key idea is that an upgrade is not a “hot‑patch” operation; it is a new generation that replaces the old one. If the upgrade fails, you simply boot the previous generation. Because the Nix store keeps every derivation in its own path, the old binaries remain untouched until you decide to garbage‑collect them.
Step‑by‑Step: Upgrading Nginx on a Production Host
Backup your current configuration:
sudo cp /etc/nixos/configuration.nix /etc/nixos/configuration.nix.bakUpdate the Nix channel:
sudo nix-channel --update– this pulls the latestnixpkgscommit.Edit
configuration.nixto request a newer Nginx:services.nginx.enable = true; services.nginx.package = pkgs.nginx_1_22; # explicit versionRebuild and switch:
sudo nixos-rebuild switch --upgradeThis command does three things: it evaluates the new configuration, builds the required derivations (including the new Nginx binary), and atomically updates the system symlinks so that the next boot will use the new generation.
Verify the upgrade:
systemctl status nginx.service curl -I http://localhostCheck that the service is active and that the HTTP response header shows the expected Nginx version.
Test rollback (optional):
sudo systemctl rebootDuring boot, press
Escto open the GRUB menu, then select the previous generation (e.g., “NixOS, 2026‑10‑15 12:00:00 (previous)”). Confirm that the old Nginx version is running.
Trade‑Offs & Limitations
- Disk space consumption: Every generation stores its own copy of packages. If you leave many generations, the
/nix/storecan grow quickly. Runsudo nix-collect-garbage -dto delete unused generations and free space. - Learning curve: The declarative syntax and Nix expression language can feel foreign to sysadmins used to imperative shell scripts. However, once you master
configuration.nix, the system becomes self‑documenting. - Imperative changes are lost: Manual edits to files under
/etcor other system locations are overwritten on the next rebuild. Keep all configuration inconfiguration.nixor inenvironment.etcto preserve it.
Practical Checklist Before You Upgrade
# 1. Ensure the current generation is working
systemctl is‑active nginx.service
# 2. Verify you have a recent backup of configuration.nix
ls -l /etc/nixos/configuration.nix.bak
# 3. Check available disk space
df -h /nix
# 4. Confirm you can boot previous generations
sudo nixos-rebuild boot --upgrade
Conclusion: The Upside of Declarative, Atomic Upgrades
Once you adopt NixOS generations, upgrading becomes a risk‑free operation. The system either switches to the new state or stays exactly where it was. The only cost is disk space and a short learning curve. For production environments where uptime is critical, the atomicity and reproducibility of NixOS upgrades are a decisive advantage.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.