Moving into NixOS

Functional package management is best package management. Therefore, NixOS is best Linux distro. [1] Here’s my journey of being enlightened and a member of the NixOS cult for 2 months.

Why NixOS?

Because I often hear the following features being tooted whenever NixOS is being mentioned.

However, most of the features listed here aren’t unique and/or can be replicated.

Plus, you can taste the power of NixOS without installing it since most of its power comes from the Nix package manager. You can install it in a non-NixOS distro conflict-free since all of the stuff are happening at its own directory at /nix.

Still, the fact that such features are built-in is a pretty great reason to try it. And the >60,000 packages (as of 2020-11-04) is a nice bonus. [2] A bigger bonus, in fact, is a lot of the packages from the AUR that I use (e.g., polybar, Zotero, Brave browser) are available as a binary.

My desktop workflow

A few days later of fiddling with a NixOS VM, I got a working configuration based from this guy’s config.

It’s the system config with some Nix modules applied on top with each module only requiring a simple flip of a switch to activate them. For example, if I want to bring in my Python installation, just set = true and the next time you run nixos-rebuild switch --upgrade, it’ll bring the configured Python environment from the related module.

Just for the sake of another example, if I want to enable certain stuff in my system, say Visual Studio Code, Zsh, Rust, and a bswpm-based graphical environment, I can simply set them up with the following lines in my system configuration (/etc/nixos/configuration.nix).

{ config, options, lib, pkgs, ... }:

  imports = [

  # <!--snip-->

  modules = {
    editors.vscode.enable = true;
    dev = {
      base.enable = true;
      rust.enable = true;
    shell.zsh.enable = true;
    themes.fair-and-square.enable = true;

This type of workflow is certainly a power user’s (READ: my) fantasy with the declarativeness and the ease of system management with my customizations. It’s pretty cool to have it realized.

Then, my Arch Linux installation broke [3] and the temptation meter to install NixOS on bare metal goes to 100%. The bare-metal installation goes out smoothly with my config stored in a Git repo.

# Assuming you've set up the partitions, enabled swap partitions, and mounted them to /mnt.

# Install a bunch of packages in the medium installation.
nix-env -i git gnumake

# Bring in my NixOS config over.
sudo git clone $MY_NIXOS_CONFIG_URL /etc/dotfiles

# Install in 3... 2... 1...
PREFIX=/mnt USER=foo-dogsquared HOST=zilch make -C /etc/dotfiles install

Even better, I can set the above snippet as a reproducible executable by just setting the shebang and removing the nix-env line.

#! /usr/bin/env nix-shell
#! nix-shell -i bash -p git gnumake

Then, the installation will be more simplified by getting it from the network (i.e., curl $MY_NIXOS_INSTALL_SCRIPT | bash -).

I still have to set up shop for my files and secrets (preferably with Unison) but that’s pretty much it and can be easily automated.

The pain, behind-the-scenes

The workflow is a result of a person with a day-worth of free time grokking Nix through trial and error. NixOS, being so far from a traditional distro, it’s a world of its own. Thus, it has its own set of problems.

  • The Nix language. The lack of static typing (which may not happen anytime in the future) and its domain-specific nature does made a harder time for me. I haven’t fully understood it until I read the beloved Nix pills series.

  • The Nix toolchain binary is spread throughout. As of NixOS 20.09, you have the nix-shell for creating shell environments, nix-build for building from Nix expressions, nixos-rebuild for interacting with NixOS, nix-collect-garbage for garbage collection, and so forth. NixOS does have Nix 2.0 that attempts to bring it all in one namespace with the nix binary and it will further improve at v3.0. [4]

  • Knowing the Nix toolchain and the language is only half the battle, knowing the conventions for writing Nix packages as well as finding functions between the manuals is the rest of the battle. You really need to dwelve into the source code of several Nix packages to be familiar with Nix.

  • The official documentation. If you’ve heard newcomers trying out Nix, they often mention how harsh or sparse the documentation is (which is still the case, sadly). A lot of the documentation of various functions are buried on the source code, their respective manuals, or non-existent.

  • Discoverability really suffers throughout using NixOS. The documentation, the conventions, and the scattered toolchain really made searching for stuff easily missable.

  • Due to how Nix revolves all around the store (i.e., /nix/store), it has some implications with the absence of the traditional filesystem hierarchy standard (FHS).

    • This means that you cannot easily run precompiled binaries and AppImages since most of them may rely on a linked libary placed in a traditional distro like Debian and Arch Linux.

    • Also, you cannot easily compile certain projects and practically required to create a Nix package (or a Nix shell) for that project.

  • Although the error messages are correct, they’re confusing (sometimes). My experience with debugging errors are mostly composed of looking at the error stack and guesstimating the erroneous attribute.

Final thoughts

Using Nix convinced me that functional package management is the pretty good for operating systems and package management. So much so that I’ve took interest in reproducibility and researched a lot of it in my free time.

The problems I encountered in traditional package management — e.g., downgrading certain packages to make some packages work, inability to install the same packages with multiple versions side to side without using a third-party software — is gone like a chef’s kiss. Furthermore, there are a bunch of bonus features that comes with it such as rollbacks and atomic upgrades.

Despite the problems, once I got into Nix, it’s hard to go back into traditional Linux distros such as Arch Linux and Debian as my desktop distro. The benefits I gain outweighs the negative moments I experienced from using it. If I would have to recommend it, I’ll say it’s suitable for power users who like to reproduce their setup and adventurers who want to look at a different side of Linux distros if they don’t mind the slightly steeper-than-most-Linux-distros learning curve.

Fortunately, the Linux ecosystem are starting to catch up with what Nix established. It inspired several projects from all around the corner such as Fedora Silverblue, GNU Guix, and alternative package managers for several projects (e.g., Xiden for Racket, Hermes).

With the way I see things, I think functional package management is the future. It may not be the future but it is futuristic. Still, we’ll see how this turns out in the next year or so if it still holds up.


  • [2020-11-15] Updated the reproducible executable instructions.

Appendix A: An opinionated guide on how to learn Nix

Nix throws a bunch of traditional concepts behind as well as pioneers a bunch of things creating a steeper learning curve. The official documentation for Nix is pretty great at covering ground of all Nix stuff which makes it good as a reference but horrible for a newbie who wants to gain a quick overview of what Nix is all about. So I’ll list a bunch of resources that helped me becoming comfortable with the Nix thing.

My usage of NixOS for two months is nothing more than a desktop distro switched because of its larger package set. Nonetheless, I still found some cool things.

1. There’s also Guix which is also best distro and in my to-do list to cover it sometime in the future.
2. Fun fact, it is around the same number as the AUR (as of 2020-11-04).
3. Probably because I did not read a PKGBUILD of a malicious AUR package.
4. Though, this is a minor inconvenience since you can just type nix and use tab-completion but it still gets to me sometimes.




Topic: linux.nix

Hash: bac1316eda6f2c028ffeaf2d9d87541cd7d3f2b5