Nix Turns 20. What the Hell Is It?
earthly.dev
earthly.dev
The documentation is still pretty poor in some spots though :)
It's amazing to have a system that isn't accumulating cruft as you tweak config files and to be able to completely set up a new system in an hour with all of my preferred config and applications. NixOS is dotfiles on steroids. On top of that you get easy dev environments with nix-shell and trivial rollbacks if something goes wrong. (gone are the days of manually reverting packages from the package manager's update log)
It's a consequence of Nix' goal of accountability, atomicity, and reproducibility.
- If a package isn't listed in configuration.nix, it isn't installed. That's powerful information to have.
- If you want multiple systems to run the exact same set of packages, you can do that trivially by just pointing them all to the same configuration.
I suspect it would be much harder to provide a fair answer to the question of why you _wouldn't_ deem it important to know what software is installed on your computer. That seems like a pretty significant pitfall of most operating systems.
One of the things I learned is that Nix users were just as excited about the ideas Nix represented as they were about the actual technology. Here's just one interviewee's take:
Here’s the key insight that Eelco Dolstra 1 had in his PhD thesis: we’re awful at labeling the software that we’re using in the programming community. The insight that Nix has is that we need to be more precise about the way we label our software.I’m still not sure this is right, but this is how I’ve been thinking about nix:
Packaging things is hard on Linux because you have dynamic dependencies. Everything written in C probably loads in libc. And it gets worse from there. You have all kinds of dependencies that are loaded dynamically at runtime, some crypto library, P threads, et cetera. If everything was linked into a static fat binary, it would be easy to package a deploy things onto Linux machines, but that’s not the case.
So one way to view Docker is as a hack around this issue. You can ship an application easily – You can package it up easily – If you put it inside of a box and inside that box, you put an entire Linux file system and all its dependencies.
A second solution is the one that Nix has, which is to rethink all this. When you build things just be very explicit about what the dependencies are. And when you link them, link them by hash that’s made of all the inputs, and then you don’t have collision problems. And you’ve solved the packaging problem for Linux. But it requires changing how you build programs.
I’m sure nix experts on here have a deeper understanding of things. But it’s been a useful mental model for me.---
Copied over my comment from https://lobste.rs/s/pnnoba/nix_turns_20_what_hell_is_it
It was super nice to have everything configured in a single file that specified every detail of the OS. But some things were super hard (writing my own packages) and I slowly moved on.
Many Nix enthusiasts use NixOS as a daily driver, and are very pleased with it.
I'd say some of the advantages are: the same 'elegance' from being able to declare how a package gets built carries over to being able to configure a system. -- e.g. for niche things like "setup Yubikey with PAM", I don't have to worry about what config settings to manually change, I can just update my config with that. (And my config is in a git repo; whereas "what changes I made" is not).
There are certainly significant drawbacks, sure; but I think the main decider between whether it makes sense is how appealing "take the time to write a config with changes" is vs "just run the command / edit the system file" is.
The other aspect is that declarative is nice, but often you care about preserving data as well. So you need backups etc. If you have full system backups, then separating config from data is more complex (and less useful). I’d rather spend my time on a rock solid and frequent backup strategy than worry about NixOS + a solid backup strategy.
I only have 1 server though. If I had more, then being declarative might be more useful. I currently use Nix for project dependencies, which is really nice.
You don't have to do that - there's lots of other options. (Although the system shouldn't rebuild if you don't update your channels, so the premise is interesting/suspicious.)
You can build your app independently against a pinned nixpkgs version. You can build the app and export/import that closure on another system. You can build the app itself using nix-build without engaging the nixos switch.
There’s no good way to have an auto-updating non-NixOS systemd service on NixOS, because it’s not designed to co-exist with other things.
Also, NixOS is pretty much a DSL around systemd for this kind of thing. Systemd is already fairly declarative, so the indirection seems a bit unnecessary.
Docker will arbitrarily trust the internet.
So if you make an Ubuntu image in Docker, and then you say, execute these apt install steps, it will go and contact the Ubuntu Package Manager. And it will trust the internet at that point.
So there’s no guarantee that if you try and build a Docker container using Docker today, that it will be the same Docker image that you build in a year.
Whereas with Nix, the inputs completely determine the outputs, and all of the inputs are cryptographically hashed. And all of the outputs are cryptographically hashed. So it knows if there’s a mismatch if someone has changed the source on the internet, for example, [or] a source has gone missing. There’s no way it’s going to accidentally introduce a source that you didn’t intend to go into the image, whereas Docker will just pull whatever is there."
I think this quote by Daniel Firth highlights the difference between NixOS and Docker exceedingly well...