So I kind of involuntarily switched to NixOS recently. This is the story how this happened and a couple of things I wish I knew when switching.

Introduction

This is not about super-low-level NixOS information, as you will find that primarily here. Rather, while talking about my situation I want to help you get to know a couple resources that I wish I knew when starting out, as my initial workarounds were … sub-optimal. If you just want to know my thoughts about NixOS, you might want to jump to the conclusion.

It might be an interesting story for you even if you don’t know what NixOS is. There are multiple explanations to be found across the web. I kind of like this one, though prior knowledge about Operating Systems and Linux in general are assumed.

Wanting to test NixOS

I wanted to test NixOS for the longest time. After all, one social circle of mine was entirely on NixOS. So I knew a lot of the concepts beforehand, theoretically. This helped, but led to more detailed frustrations - since I understood what is going wrong on a higher level while not knowing how to fix it on the lower one, where it actually happened.

First Encounter

Regardless, I created a boot-stick and installed NixOS on my desktop-computer. I booted with a super-minimalist configuration and was immediately thrown off because I had no idea how to install packages. More precisely: I knew that it would be possible to install them globally by including them in the configuration.nix, and locally by nix-env -iA nixos.<packagename>. But which one is the correct one for which packages? How do I configure my environment? How do I include these configurations in the configuration.nix? After being somewhat overwhelmed, I refrained from starting the desktop computer for some time.

So my first encounter did not exactly go well. It felt similar to having ‘burnt’ myself once, and while I knew that I needed to understand and configure it more before I could actually use the computer, I was avoiding it. So what changed? How did I actually ‘switch’ to NixOS?

Only NixOS

My Laptop crashed and burnt. Or, well, not exactly. For some reason, it did not boot. At first, it seemed like just part of the boot section was corrupted. So I tried to fix that. Didn’t work. Tried some more things. Didn’t work. Did a backup, and tried to install a new OS. I slightly panicked and just wanted a working OS. I tried Ubuntu first. Then Linux Mint, Debian, and NixOS. None worked. They all failed to install the bootloader - maybe due to the same reason it previously failed to boot. I already suspected an SSD failure. Regardless, I had two presentations to prepare, and they were more critical than fixing my computer.

As I was sitting in our student council room (I’m well-known there) already, and several people were aware of what I was trying to do, I just told them: ‘I can’t figure out why installing an OS on this laptop just does not work.’ There were three people willing to take the challenge. I started to prepare for the presentation I was supposed to hold in two hours, somewhat unaware of what was happening to my laptop. At some point, just before I needed to go, they were successful: ‘You now have NixOS’. It was among the bootsticks I had with me, after all. I held the presentation first, I had no time to start the computer yet.

Learning NixOS

Now both of my computers had NixOS, and I had no clue on how to work with it. I had a somewhat working computer and knew how to use nix-env -iA nixos.<packagename>, so this got me started. And I somehow started to manually copy and configure dotfiles again. While it worked somewhat, it just felt so wrong. I needed to hold and build another presentation, this time with LaTeX. On an operating system where I was foreign and had no idea what the package is called. So I googled it.

From here on, my experiences with NixOS were mostly pleasant. I expected some sort of hassle after installing LaTeX, some package missing to actually build it, or some cryptic error message. It’s always like this when trying something new. Not this time. Installing LaTeX took a few minutes, but then I was able to build the presentation again, just two hours before we were supposed to hold the presentation. I felt immense relief, to say the least. Everything would have worked out even if this did not work, but we wanted to update some details.

Packages

Even though googling how certain packages were called worked quite well, it was pretty clear that this is not the way it was supposed to work. I’m still not sure how, but at some point I became aware of https://nixos.org/nixos/packages.html, the actual searchable package repository. I bookmarked it immediately. This considerably improved both my speed and confidence when searching for packages.

A pleasent surprise what that a couple of packages from my setup which were not packaged yet for Ubuntu (ripgrep or broot) were just immediately available as a package. And not just those, also some plugins or other packages which supposedly required a different package manager first (cargo or pip) were directly available through nix. Configuration was as well. Things were off to a fantastic start.

(I learned about nix search <pkgname> today. It does basically the same on the command line.)

Local Configs

I was under the perception that the whole OS configuration is only determined by the configuration.nix. Even though you can deploy your local configuration files / dotfiles through NixOS, it might be overkill - Especially so when just starting out. Treating it just like any other new Linux installation would have saved me a bit of trouble and the feeling that I was just doing something wrong.

Manual

In my understanding, the NixOS Manual is sort of a mostly static though living document with most of ‘available’ and up-to-date knowledge about NixOS. This does not make it the best place to learn about Nix and NixOS, but it is a good place to find answers for specific questions. Since I wanted to learn more about NixOS, I started reading through parts of the manual and in other places on the internet. Frequently, the manual was referenced or linked, and sometimes, Nix-Pills where mentioned.

Nix-Pills

The Nix Pills are something like the introduction to the ‘secret knowledge’ of Nix, or at least it felt like it. They were written originally as a series of blog posts exploring and explaining the inner workings of all Nix-relevant concepts. They have been updated accordingly, but most concepts work still the same. If you are interested in using NixOS, I recommend you to at least skim over the content.

Nix (The Language)

All the configuration (*.nix) files are written in a specific functional programming language, Nix. As it is a purely functional language, I was mostly familiar with the basic concepts. Still, it was probably my weirdest experience in learning a programming language. I believe almost all of its intricacies get covered by the Nix pills, so I won’t go into detail here.

The learning experience was weird primarily because I thought that reading the *.nix files from other people would help me understand what the language was capable and how it operated. Yeah, No. Even though it was almost always intuitively clear what it did, I was utterly incapable to explain why it worked - there just seemed to exist a convenient option for everything they wanted to do. It took me a long time to figure out that I could actually search through these options.

Options

So when ‘everything is possible in Nix as long as you know how the option is called’, it is essential to know how the option is called. Or to be able to search for it - which is possible here. The options are pretty powerful, as they enable user and service creation just as well as a detailed configuration of packages. Only the sky is the limit. And well, if you need to write an option yourself for your exotic configuration, the Nix Pills got you covered. Regardless, being able to search for options transformed my relationship with NixOS. I did note use it more often than searching for package names, but it made configuring NixOS just so much easier.

Selecting old Configurations when Booting

So eventually I wrote a configuration that was just sufficiently f*cked up to not start my display manager. Nothing big in and by itself. So I did the ‘usual’: Go to login-shell tty1 and troubleshoot. I actually knew what was broken, so it was easy to fix the configuration - but not to materialize the system. That required an internet connection, and the network utilities I was familiar with were not available (my main utility is nmcli, but ip was not available either. Looking back, I think the $PATH was broken). I was really unable to fix it this time, even when consulting the internet on another laptop.

What I remembered after two hours: When booting on NixOS, you can select to boot an earlier configuration instead of the current one. And so I did. There, everything still worked, including internet. And since I already fixed the configuration it was easy to switch to the upgraded materialization of the configuration. This feature alone helped me significantly. It would not work with other package managers, since it depends a lot on how Nix works internally.

Garbage Collection

This is described in detail in both the manual and nix pills, so I won’t go in detail here. The thing is, even when removing packages from your configuration.nix or uninstall local ones with nix-env -e <pkgname>, they simply get unlinked, not actually removed. Even though it is not required frequently, executing nix-collect-garbage and nix-store --optimise every month or so will free up some space without removing any relevant data from prior generations. Obviously more can be freed by removing all prior generations via nix-collect-garbage --delete-old, but then you cannot boot in earlier generations either, so use it with care. The option --delete-older-than <period> is a much safer bet. Example periods would be 7d or 30d. In conclusion:

  • nix-collect-garbage (delete unreachable store paths)
  • nix-collect-garbage --delete-older-than 30d (keep system generations younger than 30 days)
  • nix-env --delete-generations +10 (keep last ten user environment generations)
  • nix-store --optimise (reduce disk space by hard-linking identical files)

Conclusion

NixOS promises reproducible builds and does not disappoint. Even though some things still feel rough, such as parts of the documentation or the Nix language, it really feels like a next-generation package manager. After all, it really solves reproducibility. Obviously there are still improvements possible in both Nix and NixOS, but I think it is certainly among the least-bad tools with regard to its value. I do prefer ansible in terms of usability, and by a lot, but they are just from two entirely different worlds, with Nix having much stronger guarantees to ‘same’-ness than ansible would ever be able to provide.

So yeah, I’m happy with NixOS as my main OS, and I don’t think I’ll switch anytime soon. It allows literally fearless upgrades, anytime I want or need one - since I know a rollback is easy and will work. Bonus points for it not requiring integration to my dotfiles after all.

Since I’m still using an Ubuntu-based laptop for work, I decided to write a ansible-playbook for dotfile deployment and management. I also installed nix to receive the nix benefits. A post about that is in progress. Stay tuned.

If you want to try NixOS yourself, you might want to check out this page. You can download a live-CD-image as well as a VirtualBox image there.

Edits:

  • 2020-06-11: small rewordings of … everything.
  • 2020-10-27: fixed typos, added list of garbage collection commands
  • 2021-04-25: fixed some more typos and grammatical oddities.
  • 2021-04-25: Added ‘If you want to try NixOS’-paragraph and links