Linux wasn't designed to be an immutably-configured operating system. When systems like Puppet try to apply configuration to a target server, they're operating on top of a layer which is inherently stateful, which has a propensity to cause all sorts of problems. What if somebody manually entered this server and screwed with the configuration, outside of Puppet? What if poorly packaged applications don't cleanly uninstall or upgrade properly? Systems like Puppet tend to just throw an error at the sysadmin and walk away.
NixOS treats immutable configuration as a first-class citizen at the OS level. Dependenices are not installed into /usr or /etc, rather specific versions of packages (identified by their hashes) are installed into /nix/store and then symlinked back to /usr or /etc. Different applications that require different versions of the same dependency, when packaged according to standard, harmoniously co-exist on the same server because the Nix packaging system symlinks the dependencies between each other in /nix/store.
You don't realize the full power of this setup until you make a mistake, make your system unbootable, and calmly tell GRUB to just use the last valid configuration - a few minutes later and you're back at a desktop. Conventional configuration management tool like Puppet tend to be worthless in those kinds of failure modes, and most sysadmins would be implementing backup restoration procedures.
Here's another example that is simple, but one I still appreciate: I wanted a slightly newer kernel. How do I get it, and ensure all the "downstream" dependencies are rebuilt (e.g. kernel modules)?[1]
I write this into my configuration.nix:
boot.kernelPackages = pkgs.linuxPackages_latest;
I run `nixos-rebuild switch && reboot` and I'm done. I can switch back to the last one if I wanted, but this new one takes place immediately. I just did this on a server 20 minutes ago.
There are other small things I can do with this. What if I didn't want to boot this kernel to boot, just test it?
$ nixos-rebuild build-vm
$ ./result/bin/run-*-vm
This will instantly drop you into a QEMU-KVM instance that is using NixOS with your `configuration.nix`, but if you rebooted nothing would change. (You can also specify a different configuration.nix to test other machines![2]) Or I could boot it, but just once and switch back pretty easily if something was wrong.
---
Another: What if I wanted Tarsnap backups of something? (This may be out of date, but it's my old config, and I wrote the Tarsnap module)
To start on demand. Or I can configure timers/cron to do this manually.
Lots of other small things. Binary caches, your own Hydra, remote/multi-architecture builds, etc. One time I "configured" my NixOS laptop install before getting my laptop: on a remote testing server, over remote KVM. Pushed it to git. I cloned my configuration.nix during NixOS installation on my laptop a few days later, and I replicated my laptop in 10 minutes. :) Combine this with Hydra (CI) server: You can even write tests and have your laptop configuration continuously integrated all the time?!?!?!?
That said NixOS isn't always the easiest thing to use, but it does come with some big advantages!
[1] I'm aware of DKMS (and have even worked on modules using it where it was fine) but I've still had it break once or twice. Maybe that was VMWare's fault :)
[2] If you share code between all your configuration.nix files, this becomes a lot easier.
NixOS treats immutable configuration as a first-class citizen at the OS level. Dependenices are not installed into /usr or /etc, rather specific versions of packages (identified by their hashes) are installed into /nix/store and then symlinked back to /usr or /etc. Different applications that require different versions of the same dependency, when packaged according to standard, harmoniously co-exist on the same server because the Nix packaging system symlinks the dependencies between each other in /nix/store.
You don't realize the full power of this setup until you make a mistake, make your system unbootable, and calmly tell GRUB to just use the last valid configuration - a few minutes later and you're back at a desktop. Conventional configuration management tool like Puppet tend to be worthless in those kinds of failure modes, and most sysadmins would be implementing backup restoration procedures.