> You have to learn a new OS because a lot of your prior Linux knowledge no longer applies.
This is what confused me the most.
Nix (CLI tools / language syntax)
NixOS (A Linux distro that has CLI tools, but also some CLI tools that are only available on this distro and not others, aka "nix" doesn't really work on Debian)
Flakes vs "configuration"
I just wanted to like "terraform apply" a system configuration on my Debian install.
People are obsessed with Nix because you can manage your config for their local system
Ok... Ansible has existed for 12 years? And you can use it on Debian/don't need a full OS/distro from the ground up (NixOS)
But people will come out of the woodworks to tell you how you don't understand, you're wrong, you're missing the point, Nix is the greatest.
What Ansible does is just one part of the Nix picture. Nix brings a lot more:
- Language agnostic software packaging
- Package manager
- Ephemeral dev environments
- A purely functional config language (it has lambdas - you can build abstractions)
- Closures - Nix knows every single dependency your system needs down to git revisions
- Binary caching. Everything is built from source, but you can safely download binaries that are known to be built from the exact same deps you need.
- Ergonomic cross-compilation
- NixOS modules allow for composable, modular system config. For instance, my home computers all import a shared scanner.nix file that sets up scanner drivers and installs scanner software. Sharing config across machines is so easy with Nix.
- Rollbacks - you can edit your system (even swapping out gfx drivers or the kernel) and if it doesn't work, trivially rollback. As in you can restart your computer and choose to boot into the previous config.
- Easily modify _any_ dependency. You can apply patches, point at a fork, or just tweak its packaging.
The only way ansible could be somewhat like nix is if you reinstalled the same exact version of the target OS each time before you run your playbook. The problem is that ansible, puppet, salt, chef, et al, are simply tools to mutate the giant bag of state that is a Linux OS. Even then getting to the same end state is a suspect proposition unless you're extremely diligent in pinning things like exact package versions and ensure tasks run in the exact same order every time.
While these tools are good at making certain changes, and are even pretty good at detecting and eliding already-done work, they are _not_ idempotent. There are nearly no modules that properly handle unmaking their changes, so once you mutate that bag of state you're left with a state vector that is barely better than completely undefined.
If you're familiar with these tools you have no doubt deployed undo-this-change tasks that you leave in the tasklist until you're fairly confident it's run on every system the do-this-change tasks ran on. Even if a module does attempt to offer an undo-the-state functionality, you can't just remove it, you have to first configure it to run in the "undo" configuration before you remove it.
Not the person that said, but let me try. First, Nix isn't for configuration management, it can do bunch of other things, but even when it comes to configuration management it is still superior to the popular tools:
Ansible/Chef/Puppet/Saltstack
They try to be declarative (following less popular CFEngine) but they are still iterative. Saltstack is closest as originally the order of operation was based on the declared dependencies.
They still ultimately come down to just perform iterative steps, with the difference that operations are idempotent.
The biggest drawback they do have is coming from the fact that they have system with a state and they modify the system state to get selected files/services/packages/etc in new state.
Nix lives up to its name, and when configuration happens it starts from nothing and then builds everything based on the configuration.
The result of it is, let say you use the traditional CM tool to install a package. Then later on you decide the package is no longer needed so you remove "pkg.installed" declaration. What actually happens though is that the existing systems will continue to have the package installed (until you add "pkg.removed"). What's even worse is that any new instance you spin up will not have the package installed, so everything will be drifting. This is the primary reason why there was the immutable system movement. That's all to avoid those scenarios.
In contrast, in Nix, if you remove package from list of installed packages, or you remove file that you declared by nix config, they will be gone from the system. The configuration is basically describing your system.
Now, as mentioned above, that's just one piece of things Nix can do. I primarily use it for reproducible builds I really like that if a package won't build on your computer it probably will fail to build on mine as well (it's something that docker promised, but IMO failed to deliver), but let's stick to configuration management.
Another big thing is that all changes are atomic, you either get your change or the change did not apply due to error, you will not get in a in-between state, like frequently happens with CM.
Another thing is (and what I wrote above is prerequisite for this to work correctly) is that you can do rollbacks. And it works with things that are considered hard. For example NixOS by default use X11, but you can enable Wayland with some configuration changes. Then you can just revert the config back and get back to your old X11 installation.
This also makes system upgrades less dreadful.
Let's say you have your setup, but you need to use different version of openssl or maybe compile it with different flags. In traditional OS you probably would not do that or if there was a vulnerability you would wait for help from vendor as there might need to be multiple packages updated. But if it is something smaller, maybe you need python package, you would build your own version, you would place it in artifactory, then have ansible task to upgrade it on your instances.
With nix you will use overrides[1]. Nix then will see it, and if the compiled version is not in its cache it will pull all dependencies and recompile it automatically then place it in its cache.
If you set up a binary cache yourself (you can either use SaaS solution, or even just set up an S3 bucket) you can have your machines automatically pull the compiled version from it. Nix doesn't care about versions of packages either (the versions are only for the user) instead it uses cryptographic hash generated from things like source code, package dependencies, architecture, compile options, etc) this means if you cache compiled version and modify package to add some other options, it won't accidentally use the other package it will either pull the right one or recompile the code.
> I just wanted to like "terraform apply" a system configuration on my Debian install.
I think 'like Terraform, but for the system configuration' is an apt description of NixOS. -- i.e. NixOS is a Linux distribution built around using Nix to generate the system config.
The Nix package manager itself happily works on other Linux distributions. (And on macOS).
> ... Ansible ...
Nix's main focus is on packages. It happens to incidentally do package-related stuff quite well, which is why nix also gets used to declare development environments, build Docker/VM images, or used to configure NixOS.
An interesting set of terms related to Ansible vs NixOS: Ansible is 'congruent', in that it tries to get a system to a desired state by comparing what's there with what it expects. Whereas, NixOS is 'congruent', in that the system is built to be in the desired state.
> But not the "Nix system config manager", which is grouped under the same set of CLI tools, is that right?
The `nixos-rebuild` command is what you'd use to apply a NixOS configuration (that's NixOS only). (I believe it's possible to run the command to build a configuration on non-NixOS).
Whereas, the other nix CLI programs are mainly `nix-build`, `nix-shell`, etc. which are now grouped under a single `nix` command.
> Packages or system configuration or both?
I'd say packages.
That people like NixOS for its declarative system configuration is incidental.
Nix's key idea is symlinking everything. You put a package in some directory under /nix/store, where the address is computed from that package's inputs. (e.g. what compiler to use, what compiler flags to use).
If you build the same package with different inputs (e.g. different compiler versions), these packages can exist alongside each other in /nix/store. Nix can then build a PATH using whichever package you want to use. It's able to come up with ~/.nix-profile/bin and ~/.nix-profile/include (and share, etc.), symlinking to the stuff in /nix/store.
NixOS essentially 'just' applies that idea, but symlinks stuff under /etc to whatever /nix/store package has the system configuration. (Plus uses systemd services, and a few other things).
e.g. when I `readlink /etc/hosts`, it resolves to `/nix/store/n5ijm9zzkcm7qglsqrfvnixih0q7dskb-host`, or /etc/fstab to /nix/store/xb7jmzd0wy0wy4vihh0q17m81kmqgc7y-etc-fstab.
Genuine question: If Ansible on Debian works perfectly for your use cases, why are you checking out Nix/NixOS at all?
I am also mostly an Ansible-on-Debian user, and know for a fact that NixOS has a few things that might be interesting to me in the future. But I don't want to be yet another person "coming out of the woodwork" :) But for a lot of people, Ansible-on-Debian should solve their problems pretty well!
This is what confused me the most.
Nix (CLI tools / language syntax)
NixOS (A Linux distro that has CLI tools, but also some CLI tools that are only available on this distro and not others, aka "nix" doesn't really work on Debian)
Flakes vs "configuration"
I just wanted to like "terraform apply" a system configuration on my Debian install.
People are obsessed with Nix because you can manage your config for their local system
Ok... Ansible has existed for 12 years? And you can use it on Debian/don't need a full OS/distro from the ground up (NixOS)
But people will come out of the woodworks to tell you how you don't understand, you're wrong, you're missing the point, Nix is the greatest.