My Experience with NixOS - Part 2: Deeper and deeper

  • Post by Maxime Cote
  • Sep 13, 2020
This is part 2 of a series on NixOS; for part 1, click here

Now that we have a better understanding of how NixOS work, it’s time to see what tools can help if you go on that journey. First thing right away, you most likely won’t get it done in a weekend, even with gallons of coffee. That was my belief at first, “I’ve installed enough Linux, I’ll be fine in a weekend.” The reality was a lot closer to 2 weeks off and on as I get used to the OS and discover new things I missed initially. Hopefully, my experience will make that faster for you, but it’s still a very organic process and takes time.

Initial Setup

The main installation and first generation of configuration did only take me the weekend, but there’s a lot more to it than that with NixOS. You have to set up all the packages and config in the configuration file, and some “work everywhere” things turned out not to work in Nix. Speaking of things that don’t work everywhere, I’ve included some facts and things to know in quotes throughout this article:

Did you know, appimage by default don’t work, they won’t execute at all. That happens because NixOS requires binary patching of executable. Thankfully, you can use appimage-run to run them, and it handles the setup for you.

Usually, the problems you run into with things that previously “just worked” have a workaround, but finding and implementing them takes time. One easy way to find those problems early is to use one of the NixOS VM Image. Run the VM from the base image and set that up on your current computer. From there, try to make it just like you would your full computer; the important part is to go as close as you can get. We’re talking “breathing down your neck” close for it to be worthwhile. Since Nix config works the same across all computers, what you do in the VM is not lost. You can start to play around with the “configuration.nix” file of the VM to experiment with things. Some parts there, like the hardware and import for VM, won’t be reusable. But the actual config you write and create will work fine.

Did you know, while most of the packages pull from git or a remote server, it’s not mandatory. You can create a package that uses your local file for installation if you need to, but you need to share them with other computers.

Once you have a good enough build, copy the files over and migrate your full computer. It’s how I did it myself; the main issue I ran into with that is that I did not push the configuration far enough. I didn’t go above the base apps' setup into actual apps configurations and custom settings. If I made it further, it would have saved me many surprises and headaches with the migration.

Copy Other’s Config

In the vein of saving time, remember this is not school. Copying things is not bad and frown upon. I would even go as far as to encourage you to copy some things, given some warning below. Many people use Github to host their NixOS files and are also public, so go take a look. The main OS documentation will get you to a working system, but you need to know what you want and need for yourself after that. There will also be surprises, things you would take for granted that are not the same in Nix. That’s where copying other’s config can be useful and save you a lot of time. Those peoples already went ahead and found how to do the thing; you should build on that instead of doing everything from scratch. There are still cases where you will have to rely on search engine and documentation reading, but those will usually be if you have particular needs or some lesser-used app.

Did you know; you have to enable dconf separately from Gnome? Even though many of the Gnome apps use it to save settings and communicate. If you use gnome and don’t have it on, you will run into weird behavior.

As I said, there is some caveat to copying things; the main one being, do not blindly copy-paste. Since the configuration is the foundation of your system and how it works, you should have an understanding of what everything does. Knowledge is a crucial distinction when copying others. Do you know the gist of what this config does? You don’t have to understand all the details, but enough. That is the same with code and StackOverflow answer; you get the solution, but blindly copy-pasting it won’t get you far and can be dangerous.

Did you know, nix-channel and the channel settings are essential? Make sure you have the same channel enabled that you used for the configuration. I’ve lost countless hours debugging weird behaviors that were due to a channel mismatch.

Just blindly copying files or chunks of config will turn your file into a big pile of spaghetti that will be impossible to maintain. While spaghetti is a tasty and fine meal, it’s far from the best when it comes to code or config. You will end up with some unintended side effects in your system that you cannot debug since you don’t understand it. If you desperately need to get that part in there and don’t have time to figure it out, put it in an external module. Nix configs are all very modular, and you can split them however you want. External code is an excellent use-case for those modules.

Treat it like code

The Nix language is close to a full-on programming language, and so you should handle it at such. Like other programming languages, make sure you close your functions, end your lines with “;” and try to keep consistent indentation. On top of that, it’s a good idea to comment on parts that are not explicit or that are workaround for the current problem you have. Doing that will help your future self when you reopen the file in a couple of months and don’t remember anything. If it’s not explicit by itself or commented, you will have forgotten it. In that case, you’ll have to spend time trying to figure out what it does and why, so save your future self headaches and write comments.

Did you know you can very easily override and configure any of the official packages from Nixpkgs? It’s handy if you want custom configurations or a more up to date version. They can be pulled from the nixpkgs GitHub repository and then changed however you need.

Like any other programming work, don’t wait till you have done hundreds of changes before compiling. In Nix, that means running the configuration test commands sudo nixos-rebuild test. It will then execute your file and do the changes, but not push them as the current “live” version. That way, you will have the latest changes until you reboot or make them permanent with sudo nixos-rebuild switch. When you first start, you should do that a lot and iterate fast, since you’re learning what works and what doesn’t. That’s also why you should do it in small chunks. Small chunks are faster, and you can quickly see what broke the config or test what is supposed to have changed. Too many changes are tough to test at once, and you will end up with broken things you never noticed, then have to try and trace it back to the root cause.

Helper tools

All of this can look daunting, but thankfully, there are many tools to help you with those tasks. That’s also one of the beauties of NixOS.

Learning tools

Those tools help you learn the Nix language, how it works, and imperative configuration:

  • Nix REPL is a live interpreter that allows you to test configuration, see current options, and play around with the language. You can also use it to look into packages to see how they work or try things:
    • Command: nix repl '<nixpkgs>'
  • Nix-env is the non-declarative version of the configuration. You can manually install packages this way and, for the most part, they’re separate from the declarative version. The main problem with using this, other than sparingly, is that it breaks reproducibility. Using this way is going back to having to remember things, but in some cases, it’s the only way:
    • Command: sudo nix-env -f <config.nix> -iA <package>

Wrapper tools for non-nix packages

While Nixpkgs has many packages and tools, sometimes you need a wrapper to get what you need or help with configuration. That’s especially true with libraries packages manager (npm, pip, etc.):

  • Match-nix is for python packages and environment; it takes your requirements.txt and generates nix modules. This module allows you to get your python setup working pretty quickly without in-depth knowledge of Nix.
  • Node2Nix is for node and NPM install package. Works very similarly to other wrappers; it generates a node module to integrate it into your config.
  • Dconf2nix allows you to take your current exported dconf settings and turn them into a nix module. It works pretty well for most settings, but it has some limitations, so not all settings will work. That module allows you to configure your Gnome settings in a nix fashion.

NixOS tools

Those are tools that help with NixOS itself. They’re helper for config, development environments, and other nice things:

  • Nix-shell is one of the nice things about Nix for development. This app will generate you a new temporary shell with any package you want inside. That means you don’t need to install things like Java system-wide, put them in a shell for use when you need it.
    • Command: nix-shell -p <package>
  • Lorri, If you want to go further with Nix-Shell, this is the app for you. It helps with a lot of the shell’s limitations, things like updates, rebuild and caching. It also uses direnv, which makes it very powerful, simply cd to the folder, and the whole environment is ready.
  • Home-Manager is an app that allows you to treat your home folder and any of its dotfiles the same way as NixOS and packages. You get generation, reconfiguration, everything is read-only and can be rolled back. That is what allows you to have a consistent layer setup above the system for users.
  • Hydra and Nixpkgs are the main ways official packages get built and distributed. Hydra is the continuous integration server that builds and tests the repo update, and Nixpkgs is where the source files for all of the packages are. Very useful to see what’s already done and find details on some undocumented things.