NixOS and Flakes Book: An unofficial book for beginners (free)
nixos-and-flakes.thiscute.world
nixos-and-flakes.thiscute.world
So that's just to say I think it at least warrants a mention, it's helpful for a beginner to be aware of, even if they don't use it (once informed they can decide for themselves if they need that piece or not).
Nix doesn't need any more home-manager tutorials, because it doesn't need any more small-time tinkerers. It would benefit more from becoming essential to a bunch of businesses who will become invested in making their own developer experience acceptable at scale, and who will have to improve Nix to that end.
Pretty soon a bunch of people are going to realise they actually do need the exact same version of every tool in every toolchain on every machine in a team, to make use of the transformative caching abilities of tools like Bazel and Buck2. And if that catches on, I would not be surprised to see an alternative Nix frontend configured in Starlark, like every other tool in that arena. There's already a buck2-nix that generates dhall under the hood.
As far as I'm aware multi-user (as in human login users) Linux systems are almost entirely - literally - academic. Supporting it does leave some warts and complexity to be experienced by the majority single-user system users.
Yes, home-manager + darwin is added complexity that is making this harder for me; when I am encountering problems I am not always clear on where in the three systems it lies. But I probably wouldn't be journeying into Nix if it wasn't for home-manager + darwin; what I want is managing my workstation and setting up ad-hoc development environments, not configure servers.
Home Manager isn't necessary for declarative management of the user environment -- Nix flakes can do this, too. A long time ago, I kept a single `flake.nix` in my home directory describing the packages that each of my machines needed, and ran `nix profile install .#packages.<machine>` to install them into my user profile. By doing things this way, I learned a lot about writing flakes, and this transferred to other places I used Nix.
What this doesn't do that Home Manager does is dotfile management, but that's actually why I avoided HM originally. First, HM's approach is a bit clunky for my taste: each change to the configuration must be followed by running `home-manager switch` for the changes to take effect. I found this to slow down the edit-and-test loop when making changes to my shell config, etc. Second, the idea of doing all configuration in the same Nix language is cool, but most of the documentation found online about configuring, etc., `git`, will refer to the tool's usual method of configuration.
So instead, I made a quick Python script that manages package installation with Nix, and dotfile management with GNU Stow. The dotfiles and Nix configuration all go into the same git repository in my home directory, so they are tracked together. I've been using this approach to manage several machines for a few years now, and it's been more than sufficient for my needs.
That way you don’t have to do home-manager switch when a dot file changes.
My dotfiles managed by nix(-darwin) and home-manager breaks every time I update my pins, and I find myself having to bisect which commit introduced the issues. Given that, I just don't see how that would scale to a full OS, let alone to a team at work. 1000% better simpler with understandable Dockerfile and Kubernetes YAML manifests, or with Ansible YAML. At least every folk can StackOverflow and ChatGPT it to a working state, and have it work for a considerable amount of time without further maintenance.
In the very worst case, you update components individually until you find the offending one.
I've used both NixOS and nix-darwin for 2 years professionally now as daily drivers, and have had generally nothing but great success. I'm not fearing an OS update actively breaking my environment (which I can't say the same for macOS, as much as I am a fanboy of Apple).
But with all due respect, asserting that everything outside of home manager is “not worth using” is fertilizer.
The fact that smart companies (TailScale and Shopify come to mind, but there are zillions) are willing to cope with those (obnoxious) gaps is very, very strong evidence that there’s a lot worth using.
git was considered too hard, inadequately documented, maliciously baroque for years before GitHub happened.
Nix solves a harder (and more important) problem in a similar way.
Some examples: managing patches for applications is doable with NixOS. With overlays they survive updates and if they no longer apply, build fail before they can have production impact. Doing the same with docker is a nightmare and different for every dockerfile without a common interface around it. Ansible takes the previous state of the system into account which is terrible if you want to manage it fully declarative. Worst case in NixOS you do a reboot and your config applies almost no matter the previous state.
And that you can leave something running without maintenance is naive and it will start to slowly rot.
I've spent over a year making my personal Nix config work well for others: https://github.com/dustinlyons/nixos-config
At least half of the code is simply unreadable even to a person with good eyes. Some examples: https://nixos-and-flakes.thiscute.world/nixos-with-flakes/do... https://nixos-and-flakes.thiscute.world/nixpkgs/overriding etc.
Simple black-on-white with no syntax highlighting is better than this.
I can read it, but I can understand having trouble with dim gray text on a black background.
On a high-contrast, high-brightness screen, white on black becomes glaringly bright and produces halos, while a pure white background actually hurts your eyes. So you default to gray-on-gray because that's what's pleasant, while higher contrasts are used in scenarios where you want glare.
(Games and photographs, mostly.)
On a low-contrast screen, which describes a lot of cheaper hardware, the exact opposite is true.
The real issue is it's all relative to what your display hardware can do, instead of using absolutes. HDR modes fix that, but HDR is still rare.
I feel like this book jumps into flakes too soon. it should have more around the configuration.nix file, its purpose and uses, and then show systematically why one may need a home.nix file and then maybe show why something like configuration.nix/home.nix might not serve some users (and then introduction flakes for those individuals.)
it took a ton of time before I finally switched to flakes. They really need better messaging about this because the environments are incredibly complicated.. the possible choices are cumbersome.
The problems are a matrix of - root daemon or non-root daemon - nixos or non-nixos - home-manager or non-home-manager - what OS are you on? - flakes or non-flakes - stable or unstable
i'm happy with nix and love it but i definitely stumbled on al lof the mentioned
But there's no chance I would want it on my development machine. Even something as simple as installing a python package that isn't in the main repo doesn't have a straightforward solution. There are half a dozen different approaches people take, almost none of them well documented. And most of them involve writing 50 lines of esoteric nix, your own derivation, or a complicated flake (which everyone says to use, but there isn't good documentation). Maybe it is great for those on the inside, but from the outside it looks like a disaster. And that's the last thing I want to deal with when I need a package installed to get my work done.
I'd describe Nix as 95% wonderful, 5% hugely painful.
I learned Nix by using it on macOS/Linux before trying NixOS. I was concerned that NixOS would be very difficult to use.
It was easier to use NixOS than I expected; the main problems I ran into were when a tool would helpfully download some kind of binary, but since NixOS doesn't put its shared libraries where other Linuxes do, these programs wouldn't work. -- Though, for a popular-enough tool, most likely someone else already has a Nix package written that helps out.
There are other "escape hatches". e.g. I think something like distrobox could be used if native-on-NixOS stuff has problems. https://github.com/89luca89/distrobox
Nix can otherwise be difficult if you need to write some Nix code. There are several concepts in Nix which are foreign enough to how things have been done before; e.g. when building a package, it won't have access to $HOME; but, recent language tooling will often want access to $HOME. -- If something goes wrong, you may often need a wider and deeper understanding compared to if something goes wrong on a more typical Linux distribution.
For as difficult as it is, the trade-offs Nix makes are essentially "I'm going to put in a lot of effort now, so that I don't have to put in effort some time later". (This favours Nix when "effort later" is multiplied many times).
Overall, as a choice for "I need this to work right now", I'd recommend against NixOS (especially for someone who doesn't know Nix).
[1]: https://nix.dev/concepts/faq#why-are-flakes-controversial
[2]: https://discourse.nixos.org/t/experimental-does-not-mean-uns...
An RFC was recently accepted to commit to forming a plan towards stabilization of Flakes: https://github.com/NixOS/rfcs/pull/136
Personally, I don't believe there won't be any breaking changes, but I also believe that the stabilization of Flakes is still a ways away and hope that there will be a reasonable migration path.
With a transpiler to convert Nix to whatever it uses. Nickel?
Maybe it'll be better someday? We can hope. It's certainly incomplete right now, and the documentation is mostly nonexistent, but I don't think my use-case (incrementally replacing Nix) is supported at all.
The problem is that implementation of these ideas is fairly hideously complex for the intelligences of most current humans, and that simplifying that complexity requires even MORE intelligence (or more years of more people staring at the problem until the simpler picture becomes clearer).
For better or worse, Nix has owned the zeitgeist for several years now, and I'd be surprised to see it dethroned before the next paradigm shift.
Well, how did I not even realize that until now? Wow. An out-loud "holy shit" was hearable over here as I learned THAT one.
I have a number of personal machines, but I tend to mirror whatever I need to use at work; currently mostly Ubuntu.
Nix seems Great to help cleanup my ansible deployments, but it also seems problematic with the lack of LTS releases to where I couldn't potentially roll out at work.
It's very weird, because I went from "WHY IN GOD'S NAME WOULD ANYONE WANT THIS?" to "my life is now measurably better" over the span of about 48 hours, and I have no idea what clicked. Something about adding flakes to the mix (NixOS + HM + flakes) broke the logjam. Or maybe it was simply how damned useful this config was to learn from:
https://github.com/Misterio77/nix-starter-configs
I went from that to a per-user, per-machine (with defaults for each) config in about an hour, and I haven't fundamentally changed that setup since. I have no idea why it's so compelling to me, but the combination of being able to tell the machine how to configure itself in one place with the ease of adding software ... I'm going to spin up a config this weekend and put it on my kid's laptop. There are other tools to accomplish the same thing, but NixOS is just so easy ... and poorly documented ... and has weird CLI conventions ... and doesn't do a super job of garbage control ... and
Nix is a very powerful tool for dealing with packages. NixOS uses the package manager to manage the system configuration.
With a declarative config, you mitigate the risk of "I made this change, forgot what that change was" (or otherwise systems becoming out of sync with each other). Ansible also solves this, sure. (Though, NixOS forces a system into a target state).
Especially useful for working on more than one machine is the ability to conveniently install the same sets of packages everywhere. -- The standard thing to do is just run "install <package>" on each machine. Whereas with Nix, you can write a meta-package of packages you want, and either install this system-wide, or just have those packages added to PATH for when you need them.
With Nix, you pay an upfront cost, so that later you don't have to pay the cost later. -- It's a similar trade-off to using Ansible, or using a dotfile manager across machines.
Nix's reproducibility has benefits, too; before using Nix, when picking up a side project would often require that I'd update the code, as system package managers updated their package versions. -- With Nix, it's easy to retain references to old versions, and possible to have both old and latest versions of a package available on the same system.