Nix shell and Awesomeness: An Intro

3-minute read

Last year while working with @amitu, I came across this wonderful tool called Nix.

I have been using Nix for almost all my projects now. I have written nix recipes for:
rust, python, nodejs, elm, postgres, react, etc.

About Nix, its wiki says:

Nix is a package manager and build system that parses reproducible build instructions specified in the Nix Expression Language, a pure functional language with lazy evaluation

Nix maintains the package versions including system libraries across OS environments and, hence never uses dependencies from the host system. All the version information is saved in your nix recipe (which you invoke through nix-shell command, we will see below). This way, Nix can be used to create a virtual environment.

Lets setup an environment using nix-shell

This is a recipe for creating environment with python 3.7.

  • Lets create shell.nix file with:

    with import <nixpkgs> {};
    with pkgs.python27Packages;
    
    stdenv.mkDerivation {
      name = "python-env";
    
      buildInputs = [
        python37
        python37Packages.pip
        python37Packages.virtualenv
      ];
    
      SOURCE_DATE_EPOCH = 315532800;
      PROJDIR = "${toString ./.}";
    
      shellHook = ''
        echo "Using ${python37.name}"
    
        [ ! -d '$PROJDIR/python-dev' ] && virtualenv python-dev && echo "SETUP python-dev: DONE"
        source python-dev/bin/activate
        # python -m pip install -r requirements.txt
      '';
    }
    
  • Run:
    nix-shell --pure shell.nix

    --pure flag will create an environment that more closely corresponds to the “real” Nix build

This will download Python 3.7 and all its dependencies, build it and start a nix virtual environment.

With Nix, Life is Awesome

  • Nix allows to have multiple versions or variants of a package installed at the same time, especially important when different applications have dependencies on different versions of the same package
  • Nix never uses host dependencies (“global” locations like /usr/bin), it always builds with exactly precise dependencies every time, and will always refer to them from then on.
  • Nix lets you roll back changes atomically, even upgrades are atomic.
  • nix-shell lets you make build environments that are totally reproducible across machines, and don’t interfere with each other.

Read all features here.

Issues I faced

  • Nix will store multiple versions of your builds, this will use lot of your disk space. You need to clean-up regularly using Nix garbage-collector
  • Configuration (toolchain etc) for CLion/PyCharm gets reset whenever I update the packages, or switch between projects with different versions.

This is the price of having multiple generations, multiple profiles, multiple versions of software, the price of having many possibilities.

Extra

  • NixOS based on the Nix package manager and build system.
  • Nix Expression Language is a pure, lazy, functional language, to describe packages, compositions of packages, and the variability within packages. We do use this for writing our nix recipes, but it is simple to understand unless you are doing very complicated stuff.
  • Nix can also be used as your home manager but I am yet to try it.