Five years ago, I migrated my VPS from Arch Linux to NixOS.

I had no idea what I was doing. I had never used Nix before. I thought I could figure it out.

Five years later, I’m still running NixOS. And I still have no idea how it works.

Nix is notoriously hard to understand.1 Why is that? I don’t know the general answer, but I know why it was hard for me: the amount of indirection. I don’t mean symlinks; I mean the disconnect between “what you want to do” and “how Nix actually does it.” Anyone can say “use nix-env -i to install packages,” but in order to use Nix effectively, you actually need a pretty good understanding of what that command does.

Why? If all you want to do is install git with Nix or whatever, then sure, you don’t actually need to know anything about Nix. nix-env -i git, right? Wrong. I mean, you could do that. But you actually want to say nix-env -iA nixpkgs.git. Why? Don’t worry about it.

But of course you’re going to worry about it. You’re immediately confused and upset and curious what the difference is between those commands. And in order to understand why you want to use this most basic command, you suddenly need to learn quite a lot about Nix and the expression language and the directory structure that nix-env expects and how channels work and you find yourself suddenly staring at this abrupt complexity explosion that you were absolutely not expecting.

So you stop using Nix. Or you just memorize the “right way to do it,” and every time you type it, a part of you wonders why, until eventually your mind crystallizes around this idea that Nix is confusing and weird and too hard for you to figure out.

At least, that is what I remember from my time trying NixOS: lots of high-level abstractions implemented on top of very low-level primitives. It was easy to regurgitate commands without understanding them, but any time I wanted to do something without a detailed tutorial of how to do exactly that thing, I was completely lost. I felt like a tourist wandering around Paris with nothing but a phrasebook, desperately trying to find a bathroom.

So I decided to learn some French.

I gave Nix another try recently, and I took a very different tack than my first foray five years ago. I read the manual, in detail.2 I ran every command. I tried to understand not just what the commands “do,” but what they do: the files and directories and concrete operations.

And I took notes.

This started as just a way to help myself: I wrote down questions when I didn’t understand things, so I wouldn’t forget to come back to them later. I wrote down things that I learned, because the act of writing something down helps me to remember it. I wrote down the way that I felt as I went through the manual, because it’s so easy for frustration to give way to embarrassment when you realize your “obvious” mistakes.

Shortly after I started doing this, I realized something: my notes could make for a really boring series of blog posts.

Or really, a very niche series. Because I sort of had an audience in mind: whatever nameless saint is out there, toiling away for free, trying to make Nix more approachable for mere mortals.

Despite its reputation as difficult or even “elitist,” there are people who care quite a lot about making Nix more approachable: they’ve written long, thorough manuals; they’ve made a beautiful website, complete with nice little tutorials. Most visibly, perhaps, they designed a new nix command-line interface for the launch of Nix 2.0, so that you can type nix search instead of nix-env -qa (for example).

And wouldn’t it be nice for them – I thought – if some rando came along and started yelling his opinions about the Nix documentation on the Internet? Wouldn’t they just love that? It would be all the fun of someone doing an unsolicited code review of one of your GitHub repos, but with the added subjectivity of English prose and pedagogic theory.

I kid, but only slightly. I recognize that no one asked me to learn Nix, and I definitely recognize that no one owes me anything. I did this, first and foremost, because I found it fun. I like to learn things, and I like to write. If someone who contributes to Nix ever actually sees these blog posts, I hope that they take them for what they are: a weird kind of user acceptance test. Not demands or complaints, just the story of one person’s experience.

“Now, Ian,” I hear you think, “if you find a problem with the documentation, or something you think could be clearer, why don’t you just fix it? It’s open source, after all.”

First off I want to thank you for bringing that up; that’s a very good point. My answer is two-fold: (1) I don’t know how, and (2) I might not want to by the time I do.

To elaborate: maybe one day I will be that Nix contributor. But I can’t be, right now. I don’t know how to explain Nix! I barely understand it myself. By the time I do understand it well enough, I probably will have forgotten everything that confused me about it in the first place, and I won’t be able to write anything targeted at beginners. I’ll look at statements like this (from man nix-env --install):

By default, args is a set of derivation names denoting derivations in the active Nix expression. These are realised, and the resulting output paths are installed.

And nod my head wisely. “Crystal clear,” I’ll say to myself. “Nothing to change there.”

But the second point is, I think, more likely. I might never become that person. I might give up. I might decide that Nix is not for me, thank you very much, and move on to some other shiny thing. It takes me quite a lot of determination to overcome the social anxiety of “getting involved in a community,” and there’s a good chance that I will never get there.

So I’m writing this, in a way, for two people: the hypothetical future Ian that loves Nix and wants to spend a lot of time and energy making its documentation a better place, and needs a good reminder of what he found confusing all those years ago. But also for someone else: someone who actually exists, and who is probably already in the Nix IRC, who stumbles across these dusty posts one day and finds them edifying.

So. What follows will be a real, honest account of my experience trying to learn Nix (again). I will do lots of dumb things, and I will make lots of wrong assumptions. And you will get to see it all, in excruciating detail.

Excited? How could you not be. A series of blog posts about someone you’ve never met reading a manual about an obscure piece of technology you’ve barely heard of? It doesn’t get much better than that.

  1. Evidence: the Hacker News comment thread on every single post about Nix, anecdotes from my personal peer group, my own personal experience, your own personal experience that you have since forgotten because now you understand it so well that you can’t remember anything that tripped you up, etc. ↩︎

  2. Of course I read the manual before – both the Nix and NixOS manuals, in fact – but there’s a big difference between reading and reading, you know? ↩︎