What is this weird setup you have on your computer? Why don’t you use the default way to install packages?

I got these questions a lot since I’m using Nix. Here, I’m trying to answer them.

Wait, what IS Nix?

Well, let’s start by the basic. According to the official website,

Nix is a tool that takes a unique approach to package management and system configuration.

More specifically, according to the guide

Nix is a purely functional package manager.

I know that this can be very abstract, but these are some of the promises that Nix delivers:

  • A declarative system environment (no more “wait, how did I install this stuff? What is its configuration?”)
  • One tool to manage all languages (no more “I need a Python virtual environment and a JS env, and this specific lib that breaks my system… now I can start to code”)
  • No need for Docker anymore for dev (yes, they offer better solution. Hear that Tensorflow!? I’m talking to you!)
  • Easy rollback (no more “yes, I know that I shouldn’t have updated to the very last bleeding-edge version, but there was this nice useless feature…”).

OK. But how does it work?

Before going into the details of the magic, let’s have a look of some examples.

Example 1: multi-language development

Let’s say that we have a project that requires a specific version of Python and FastAPI, but also of Node and some JS packages.

For Python, we could set up a virtual env. But there is no equivalent for Node.

Or we could use a Docker and install everything inside: no more pollution! But then we need to define the volumes to mount. And the port to open. And… well, using Docker can be painfully slow for dev.

Let’s see what Nix proposes:

shell.nix:

{ pkgs? import <nixpkgs> {} }:
let
  python-with-packages = pkgs.python310.withPackages (p: with p; [
    fastapi
  ]);
in
pkgs.mkShell {
  buildInputs = [
    python-with-packages
    pkgs.nodejs-17_x
  ];
}

Running nix-shell will open a bash with Python 3.10 and Node 17. Even if these programs were never installed. Nix just downloaded them and installed them in its store. And you can check: Python can use fastapi, but no other package that could be installed outside Nix env. Neat!

Example 2: multi-language development and other programs

Now, let’s imagine that we also need selenium, chrome and chromedriver.

Who said this was a problem with Nix?

{ pkgs? import <nixpkgs> {} }:
let
  python-with-packages = pkgs.python310.withPackages (p: with p; [
    fastapi
    selenium
  ]);
in
pkgs.mkShell {
  buildInputs = [
    python-with-packages
    pkgs.nodejs-17_x
    pkgs.chrome
    pkgs.chromedriver
  ];
}

Tada!

Explaining the magic

To be fair, I will only explain a part of the magic. Or more precisely, I will only show you the direction, so you can explore the magic yourself :p

Let’s have a deeper look at this definition “a purely functional package manager”.

A package manager

This is the simple part of the definition. We all know what a package manager is. These programs like apt, pip, yarn… responsible for installing and managing other piece of code and files, or more globally, “packages”.

Nix is not different. It’s just the one capable of managing the most packages. It’s not an exaggeration, you can check repology if you don’t believe me.

Image taken the 15th of April

Do you see nixpkgs? These are the different versions of Nix repo. The only repository that matches Nix regarding the number of packages is Archlinux’s AUR. Not bad!

If you’re curious to know if a specific package is in Nix, you can use their search tool to have a look.

The reason there are so many packaging is that it is easy to contribute to Nix. Everything is done in a single GitHub repository : https://github.com/NixOS/nixpkgs. This repo contains every description of every Nix packages. For instance the Python modules are here.

Purely functional

According to wikipedia

In computer science, purely functional programming usually designates a programming paradigm—a style of building the structure and elements of computer programs—that treats all computation as the evaluation of mathematical functions.

This definition hide a lot of things:

  • First, Nix is a package manager, but also a programming language. This language is used to describe packages, the system configuration or everything we may need
  • Second, this programming language follows a programming paradigm that can be confusing at first (except if you come from Haskell word) but fit very well the need of a package manager: when installing a package, we don’t want side effects (hence the “pure” thing), and a functional paradigm to represent packages is in fact more natural that what it first seems.

Using in parallel of other package managers

Nix could be the only package manager you use. It could manage your kernel, your desktop environment and all your system (see the NixOS projects), but you could install Nix on another system and use it to manage only some packages. Because of this “pure” characteristics. Installing packages with Nix doesn’t conflict with other package managers. (I will not go into too many technical details, but when you install something using Nix, it only writes stuff in your /nix/store folder, and then create some symlink to expose what you need. This shouldn’t conflict with other packages installed somewhere else).

On my laptop for instance, I’m running an Ubuntu, with a Nix package manager that manage most of my user environment using a program called home manager.

Conclusion

I hope you now have a better idea of what Nix is, and the benefit it can offer.

Now if you wish to go deeper into it, I highly recommend reading: