Why I Use NixOS

and why you should too! Aug. 8th 2026-08-08

Okay! First time dipping my toes into making a blogpost, we'll see how this goes. Kind of sort of a test to see how I feel about doing this, ended up being way longer than I was expecting.

Some background: I've been using NixOS for around 3 years now, and have been a nixpkgs maintainer for only about a year less. Prior to that I've been distrohopping a lot, which took me to some interesting places - before NixOS I eventually settled into using Arch for desktops, and Proxmox VE w/ some basic Terraform + Ansible for servers.

I'll be talking about my experience with both the desktop and server sides of things, though what I say should be applicable to pretty much any usecase.

(credit to ntgn for the art!)

Declarative!

If you're reading this, you may have already heard the phrase "declarative & reproducible" being used to describe NixOS. But what does it actually mean in practice?

Let's say you're someone using Arch Linux (with all the good and bad that entails) and one day something breaks after an update. Or you plug in new hardware that doesn't work right immediately, or some proton game is acting up. Whatever it is, you go through the ritual of checking wikis and forum posts, until you fix the issue by changing some file in /etc, telling grub to load an extra kernel module, adding some udev rules, whatever. It's fixed!

Now, if you encounter the same issue on another computer a month or year later, would you remember how to fix it again? Did you write it down? Or would you need to try and remember what keywords brought you to that one specific forum post that had the solution?

In NixOS, writing it down is how you apply the fix in the first place[1].

On the server side of things, especially in large-scale deployments, this is how things are already done with Terraform/Ansible. In this case there isn't much of a difference here, except for speed - I've found that a nixos-rebuild changing something is usually faster than an equivalent Ansible playbook.

Reproducible!

Let's pretend you're another hypothetical Arch user. You just made yourself a cool niri config which you'd like to reuse later, so you put your dotfiles in git. So far so good. A few weeks later you try installing them to another system, but oh no! Niri updated in the meantime, and now your dotfiles don't work anymore.

NixOS[2] can take care of this by pinning your entire system to a specific snapshot of nixpkgs. No matter when or where you install it, if your config worked at one point in time it will always work the same way.

A side effect of this is that NixOS is able to keep multiple "generations" (snapshots, kind of) of your system and allow you to freely choose between them at boot. Want to update, but scared that something would break and you'd have to spend 3 hours fixing it? Just try it and rollback if it doesn't work. You can even 'test' a config without actually putting it into /boot, so if it breaks you can reboot back to a working system.

For servers this has been absolutely invaluable to me. Want to try some dangerous network config changes on a remote headless server? Test it, reboot if it doesn't work, fix your config, repeat. Want to update your email server for security but worried about having to spend the next 24 hours debugging some weird issue? Again, try it and effortlessly rollback if it breaks!

Modular!

In nixpkgs, we have these things called modules. Modules are how everything is defined - from /etc/passwd through networking to tailscale config - all in the universal programming language that is Nix. Just as an example, this is how you'd setup a basic nginx server:


services.nginx = {
  enable = true;
  virtualHosts.localhost = {
    locations."/" = {
      return = "200 '<html><body>yay!</body></html>'";
      extraConfig = ''
        default_type text/html;
      '';
    };
  };
};

There's a lot to talk about here, but for now I'd like to focus on how I use modules in my own configs. See, modules aren't just a nixpkgs-internal thing - if you want, you can define custom ones!

And I have. Oh god I have.

A small selection of what's possible:

  • core/hardening.nix: How I harden all of my systems, defined in 1 file and enabled with a single ".enable = true;" statement.
  • core/mullvad: A module that sets up multipath, per-connection-loadbalanced routes through Mullvad VPN servers. If I continue with this whole blog thing, I'll make a writeup about this sometime.
  • servers/cluster: A bunch of modules for enabling services in my RKE2 cluster. The website you're looking at right now is running on this!
  • desktops/home: Modules defining my KDE/Niri/Hyprland configs, this is basically the Nix equivalent of dotfiles.

Closing thoughts

Of course, NixOS isn't flawless. There's the incredibly high learning curve of a functional programming language in the first place, Nix errors are still AWFUL and worse than C++'s at times (to the point I still sometimes resort to just randomly commenting out blocks of code to figure out what's wrong), and then there's all the... everything, going on with flakes. All in all though, for me the pros of NixOS still heavily outweigh the cons. I couldn't even imagine going back to something like Arch.

If you actually read this far down, thank you so much! I hope it wasn't too boring. If you just scrolled down without reading, thanks anyway for taking the time to look at the entire page <3


    |\__/,|   (`\
  _.|o o  |_   ) )  <---- cat!
-(((---(((--------

PS: Feel free to contact me if you'd like to talk about this article or how I could improve the /blag/! I have no idea what I'm doing, honestly.

[1]: Unless you're doing some very weird things with persistent /, but... why? [2]: With flakes or something like npins, which you REALLY should be using