Stopping Configuration Drift: Managing NixOS with Declarative State
Stop treating your OS like a snowflake. Learn how NixOS uses declarative configuration and the nixos-rebuild process to eliminate configuration drift and enable atomic rollbacks.
24 Jun 2026, 12:17 UTC

The Problem: The 'Works on My Machine' System
Most Linux distributions are managed imperatively. You run a command to install a package, edit a config file in /etc, and tweak a systemd service. Over time, this creates "configuration drift": a state where the system is a unique snowflake. If your drive fails or you need to deploy a second identical server, you have to rely on a manual list of steps or a fragile bash script to recreate that environment.
The takeaway is simple: by treating your entire operating system as a single piece of code, you can ensure that your system state is predictable, reproducible, and instantly recoverable.
The Single Source of Truth
NixOS replaces the imperative approach with a declarative one. Instead of executing a sequence of commands to reach a state, you describe the desired end-state in a configuration file—typically /etc/nixos/configuration.nix. This file is a Nix expression that defines your users, installed packages, kernel modules, and system services.
When you apply this configuration, the system doesn't just "run the script." It builds a derivation (a set of instructions) that results in a specific system profile stored in the /nix/store. Because the Nix store is immutable, the system can maintain multiple versions of the same package or configuration simultaneously without conflict.
Applying Changes with nixos-rebuild
To move from your current state to the state described in your config file, you use the nixos-rebuild tool. This process computes the difference between your current profile and the new one, then atomically switches the system symlinks to point to the new configuration.
Worked Example: Adding a System Tool
Imagine you need htop and git installed on your system. In a traditional distro, you would run sudo apt install htop git. In NixOS, you modify your configuration file.
1. Edit /etc/nixos/configuration.nix:
Locate the environment.systemPackages list and add the packages:
environment.systemPackages = with pkgs; [
vim
wget
htop
git
];2. Apply the change:
Run the following command from your terminal (requires sudo permissions):
sudo nixos-rebuild switch3. Verification:
Check that the tools are available in your path:
which htop
# Expected output: /run/current-system/sw/bin/htopThe switch command not only installs the packages but also restarts any affected services to ensure the new configuration is active immediately.
The Safety Net: Atomic Rollbacks
Because every nixos-rebuild creates a new system generation in the Nix store rather than overwriting the old one, you are never truly "stuck" with a broken config. If a change causes a boot failure or a service crash, you have two primary recovery paths:
- Boot-time Rollback: The bootloader (GRUB or systemd-boot) automatically lists previous system generations. You can simply select a known-working version from the menu to boot into the previous state.
- Runtime Rollback: If the system is still running, you can switch back to a previous generation using the
nixos-rebuildtool or thesystemctlswitch utility.
Trade-offs and Limitations
Declarative management is powerful, but it introduces specific engineering overhead:
- The Learning Curve: You must learn the Nix expression language, which is a functional language. This is significantly different from writing a shell script.
- Imperative Conflict: Any changes made manually to the filesystem (outside of
/etc/nixosor the Nix store) are not tracked. If you manually edit a config file in/etcthat is managed by NixOS, your changes will be overwritten the next time you rebuild. - Storage Growth: Since Nix keeps old generations to allow rollbacks,
/nix/storecan grow rapidly. You must implement a garbage collection strategy (e.g.,nix-collect-garbage -d) to prune old versions.
Closing Action
To start eliminating drift, move your manual installation lists into configuration.nix. Once your environment is fully declared, back up that single file to a git repository. You now have a complete system blueprint that can be deployed to any compatible machine with a single command.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.