~/articles/why-nixos-is-not-for-me

Preface

Since I manage my own server, my laptop and a few Raspberry Pis, I wanted to have a universal way to install packages. I would like to have packages that preferably on stable branch and be relatively up-to-date. Installing my environment is crucial, especially my shell scripts dependencies 1.

In order to do this, I used to have a simple text file where I specify all the packages names, and I would throw that to pacman, brew or apt-get to get my environment set up. This was inspired by requirements.txt in the python world.

The problem with this approach is that most package managers don't use the same package naming system. This is indeed a very fragile method.

nix.enable = true;

Nix doesn't only solve the above rather simple issue, but also brings some powerful feature that I didn't know that I needed.

Combined with direnv, nix (precisely the nix-shell command) is able to load packages into $PATH in an ad-hoc way. This allows developers to create their environment declaratively, and by consequent share these environments.

Nix is also better versioned. For example, brew pushed the latest jdk 21 really hard and it broke my Scala setup. This wouldn't happen with nix, since the inputs (where the package registries come from) can be pinned and is locked by default. Comparing to pacman, you can also opt for the latest bleeding-edge feature by using a different package set as input, such as nix-unstable, without being all the time on unstable.

nix.enable = true; # with nuances

I think everyone knows that nix is poorly documented, here's my two cents why that is the case.

The "standard library" where all the basic functions lives, is under the attrSet pkgs. This is all written in nix. If there were better tooling support like Rust's rust-analyzer, I'm sure things would be a lot of different. Nix is not typed, and the fact that the state of the art nix language server nil can't go to the library definitions is very frustrating. I know I could've learned the language and the ecosystem a lot faster empirically, simply by navigating in the standard library.

Besides the documentation, the error message is also of extremely poor quality. I thought things couldn't get worse than Haskell 2, but here we have nix. Since it's the aforementioned nix library pkgs or other tools calling each other, the error message often only shows where the library failed, which is often irrelevant to the mistake I have made.

The evaluation speed is acceptable on my M1 Max computer, I would be interested in seeing a faster nix evaluation for sure, since it's unbearably slow on my potato ThinkPad.

NixOS ?

I like to use Nix as a package manager. Using it as the only package manager makes a lot of stuff harder, sadly. I will keep on learning about Nix, and when the moment comes, I might make the leap to using NixOS full time.

Where am I now in this nix journey?

As much as I dislike nix's implementation, I have taken the time to nixify all my tools, except neovim. Since I often rewrite or modify my configuration, I would like to keep it portable and not influenced by nix. Configuring neovim is complex on its own, I would like to keep it simple by keeping it away from nix. However, I do find managing various language servers easier using nix then using mason.

My configurations have stabilized in the past week, here's how it looks like at the moment of this article.

1

My "function not found" fish script would loop if the command it's calling is not found. It's horrendous.

2

Haskell's default error message is written in the reverse direction, there's a ghc option to reverse that back.

<newer   earlier>