My opinion on Nix, The package ManagerPosted on Thursday, 13 May 2021 Suggest An Edit
I’ve been trying to dive into Nix recently and it has been pleasant. The reason is, let’s say someone mentioned it a little bit too much and got me interested.
If you don’t know about Nix, it’s a declarative, purely functional lazily evaluated language and a package manager, and there’s also NixOS which is a distribution entirely based on Nix. I won’t explain what they are in this post, so please refer to their official website.
This post is going to be focused on my opinion about it so please take it with a grain of salt ;)
I’ve decided to use Nix to manage my dotfiles and most of my packages since I moved to Fedora. I still use
dnf for GUI packages since they don’t play nicely when installed through Nix.
Here’s my flake.nix in case you want it ;)
My very first introduction to Nix is actually using it from NixOS. It’s a very unique Linux distribution, it doesn’t use FHS which has its pros and cons.
Imagine, your entire system is like a git repo. You configure the system declaratively using a file in
/etc/configuration.nix. It’s super easy to configure services, packages, etc. You can also rollback to a previous generation. Similar to how you’d do
Because you can configure everything from
/etc/configuration.nix, there is too much abstraction. I think it’s good because it simplifies things and makes it easier because everything is centralised, but it’s also not good because you no longer know which configuration goes to where.
Also, you lose the ability to run a normal binary because Nix uses a non-standard filesystem structure. You can patch them, but that seems like a bit of a chore to me.
The language is purely functional and lazily evaluated. Some people say that its syntax is quirky, but I don’t really think it is. Its syntax is quite similar to Haskell.
Quick and (overly) simplified explanation is, it adheres to the concept of functional programming which I really like. In Nix, everything (well, mostly. You still have a primitive data type) is basically a function with exactly one argument. If you want to insert multiple arguments, you’d need to use currying. It looks something like this.
# define the function sum = x: y: x + y; # call the function sum 2 5
// define the function const sum = x => y => x + y // call the function sum(2)(5)
It feels easier on the eyes than the traditional
foo() function invocation but it can also be a bit confusing at times. Learning Nix made me understand this concept, I used to be so confused why would anyone need currying and now I understand why :)
The code won’t be evaluated if it’s not being used. I personally think this is a cool concept. You can create an infinite list but you only take 20 of them, then it’s going to be evaluated as if it’s a list with a length of 20.
This concept also exists in Haskell (and probably most functional language). Might be a bit confusing for someone who never used a lazily evaluated language, though.
I don’t think the syntax is quirky, it’s unique in my opinion and I like it. If you want to know more about its syntax, please refer to this page as it’s the official page and it explains them very well and thoroughly!
One of the nicest thing out of many things about Nix package manager is you can execute an isolated shell and it can be easily reproduced. You can use
default.nix and execute
nix-shell on that directory. You can read this article or the official wiki to understand what it does
You can also execute a package temporarily using
nix-shell -p <pkgname> without installing it. It’s super cool!
It’s also cross-platform, you can install it on MacOS or any GNU/Linux distribution, though I’m not sure about the non-systemd distribution. This makes it easy reproducibility on any OS – Except Windows, that is. You can use WSL2 on Windows, however.
Now, the problem with this is since every package is ‘isolated’, some of them like
telegram-desktop won’t work properly. It couldn’t pick up the system theme, resulting in an ugly cursor. I know this is a minor issue, but it bothers me more than it should lol.
Another example is
fcitx5 which is an IME that I use to type 日本語. I don’t know if it’s my setup, but it doesn’t seem to be able to find its addons like
mozc – I can switch my input method, but it has no effect when I’m typing.
The absolute deal-breaker for me though, is any package that uses OpenGL can’t be used outside of NixOS without some sort of wrapper. I don’t really like adding a wrapper just to achieve this.
They work flawlessly on NixOS when I tried it, but I guess it’s because the entire system is designed for them.
Also, when it’s downloading something, there is no progress bar which makes it seems like it doesn’t do anything when it’s downloading a big package. I have a slow connection and I got confused when it’s trying to download something big.
I actually enjoy writing Nix build files, it’s really exciting to write them. It’s also pretty satisfying when it successfully built the package.
Though, since I don’t have a project using Nix and most of my stuff is using Node or Rust and all of them are a one-man-project – meaning that I’m the only one who works on it, I don’t think using Nix is going to bring any advantage.
I used home-manager for a few days and it has been great! It’s almost like
configuration.nix for your current user instead of system-wide.
I stopped using it though because I don’t use Nix that often (yet) and I don’t have multiple machines so using it’s probably a bit overkill.
So, here’s a summary of what I think about Nix. Again, please take them with a grain of salt as this is my personal opinion and I might be completely wrong ;)
- The language is good. Yes, there are some quirks but every language have their own quirks.
- The package manager is great! It provides a hermetic build environment. It’s super useful when you’re working with many people.
- It can be used on multiple operating systems. This is great if you’re working with someone who uses a different operating system.
- You became more nerdy than most people around you :p
- I’m not going to use it for now since I don’t work collaboratively with several people (yet ;) and most of the time I code in NodeJS related stuff, Rust, and Lua, so using it won’t bring any significant benefit. I think it would be beneficial when I do some serious low level programming that requires a bunch of system dependencies that needs to be easily reproducible.
- I already have a package manager; which is Pacman. Using both Pacman and Nix seems like a weird setup to me. If I use MacOS, I would definitely use Nix.
- I have a slow connection and low storage. Some packages from Pacman get duplicated in Nix; I know this is necessary for reproducibility but I’m not trying to reproduce it anywhere at the moment.
- I don’t want to fall too deep into yet another rabbit hole ;)
Overall, I like Nix. I can’t wait to be able to use it for a real-world situation – As you may or may not know, I’m still in High School when I write this and there’s almost no high-schooler who thinks Nix is worth investing your time into :p
Also, here’s some good articles that I’ve read about Nix that you might want to read if you’re interested.
- nix-shell with ZSH
- How to learn Nix
- Nix by example
- How to get started with Nix
- Using Nix in my development environment
Anyway, thanks for reading my post, and have a wonderful day! :)