A year on NixOS, mostly happily

A year ago I switched my desktop from Arch to NixOS. People keep asking what I think. Here's the long version.

Why I switched

I had two machines that were supposed to be identical and weren't. Two laptops, set up six months apart from the same notes, gradually diverging because I'd pacman -Syu on one and forget on the other, install a thing on one and not the other, edit a config file in a hurry. After a year of this, the two machines had subtly different behaviors and I couldn't tell you why.

NixOS is the only Linux distro I've used where this kind of drift is, in principle, impossible. Either the machine is described in a file or it isn't. If it's described in a file, the file is the truth. If it isn't, it shouldn't be there.

What's good

Atomic upgrades. An upgrade either completes or it doesn't. If it doesn't, the previous generation is still there, in the GRUB menu, two seconds away. I've had to use this exactly twice in a year and both times it Just Worked.

Reproducibility. My laptop and desktop now share most of their config. nixos-rebuild switch --flake .#desktop on one, --flake .#laptop on the other, and they actually stay in sync. After fifteen years on Linux, this is the first time that sentence has been true.

Per-project shells. nix develop for a Go project gives me Go 1.22, golangci-lint, sqlc, and protoc, all pinned, all gone the moment I cd out. No more "works on my machine" because the machines, for the duration of the work, are identical.

What's strange

The language. Nix-the-language is fine but nix-the-language-as-actually-used is a mess of legacy patterns, flakes-vs-channels schisms, and documentation written for the person who already knows. This will get better. It's getting better. It's not yet good.

Error messages. A typo in your flake produces a 400-line stack trace that ends with "infinite recursion encountered." You learn to ignore the trace and look at the line numbers. It's fine. It's not great.

Dynamic linking. A pre-built binary you found on the internet will not run, because /lib/ld-linux.so doesn't exist. You'll learn to wrap it with buildFHSEnv or patchelf or, more often, give up and find the source.

What I'd warn you about

Don't switch on a deadline. NixOS is not the OS to learn the night before a demo. Give yourself a weekend, then a week, then a month of patience. The reward is real but it's at the end.

Don't try to rewrite your whole life in Nix on day one. Start with configuration.nix, get comfortable, then add home-manager, then maybe flakes, then maybe try to declarify your dotfiles. I tried to do all four at once last winter and it took me three weeks of evenings to back out the mess.

Decide early about home-manager as a NixOS module vs. standalone. They are subtly different. I went standalone because I also use it on my (rare) macOS work and it was the right call.

One year on

I'm still using it. I haven't been tempted back. The two-machine drift problem is, I think, actually solved. I have not yet had to explain to a guest "no really it's a Linux, just don't touch anything" — they're sitting in front of sway and they just see Firefox and a terminal, like anywhere else.

Would I put it on a non-technical user's machine? Absolutely not. Would I put it on a junior engineer's first work laptop? Probably not. Would I put it on yours, if you write code for a living and you're tired of your distro slowly diverging from your notes? Maybe. Try it for a month.

The config: not public, but I'll send it on email if you ask. It's about 500 lines and not very interesting.

← archive