Nix introduction, main concepts and commands

0

Nix is a functional package manager for Linux and other Unix systems, making the management of packages more reliable and easy to reproduce.

With a traditional package manager, when updating a package, a new version is downloaded and used to overwrite its associated files. Changes can’t be undone. If for a reason, one or more files are not correctly updated during the upgrade, those files of the package are going to be corrupted. This could make the entire package not functional. In addition, if different packages require different versions of the same package as a dependency, at least one is going to be broken.

This article presents what Nix package manager is, the various deployment options and how to start with it. In the following article, we cover the installation of NixOS, a Nix-based Linux distribution.

What is Nix

Nix is a functional package manager. Below are the three main benefits of using Nix compared with a traditional package manager:

  • Nix brings reliability: installing or upgrading one package don’t break other packages. It ensures that no package is inconsistent during an upgrade. Roll back to previous versions is possible.
  • Nix brings reproducibility: packages are built by Nix in isolation from each other. This ensures that they are reproducible and don’t have undeclared dependencies, so if a package works on one machine, it works on another.
  • Nix is declarative: Nix makes it easy to share development and build environments for projects, regardless of what programming languages and tools are used.

With Nix, files are related with symlinks. When a package is installed, symlinks point to a location inside the Nix store directory, located in /nix/store. When upgrading a package, the new package files are extracted in a different location (no overwriting), the symlinks point then to the location of new files.

Usage of symlinks to refers to packages have some advantages:

  • No risk of corruption between dependencies: multiple versions of the same dependency can be installed
  • Less storage requirement: the same version of a dependency is not duplicated

The upgrade process of a package creates what Nix calls a generation. It is possible to roll back and to roll forward through the previous generations. This leaves the system fully functional because one can always roll back to a previous generation. It is possible to save and keep as many generations as wanted. The downside of this is the hard drive space used to store the generations, but it is possible to clean out old generations.

Nix deployment

Nix can be deployed on an existing operating system, either Linux or macOS, or using NixOS which uses it from the ground up to create a Linux system.

Deployment through NixOS

NixOS is a Linux distribution built on top of Nix. The installation of NixOS share the steps of an alternative Linux distribution: partitioning and formatting of the disk before installation of the operating system. The official documentation gives steps to follow to deploy Nix through NixOS installation.

Deployment on an existing operating system

Nix is supported on Linux (i686, x86_64, aarch64) and macOS (x86_64, aarch64). Below are the commands to install Nix:

  • Linux

  • MacOS:

    sh <(curl -L https://nixos.org/nix/install)

Follow the Official documentation for more about installation on an existing operation system.

Usage of Nix

User Environment

A User Environment is a set of active applications. Different users can have different environments and individual users can switch between different environments. ~/.nix-profile is a symbolic link to the current user environment.

Managing a user environment is done either via declarative configuration using Home Manager or via imperative operations using nix-env commands.

Home Manager

Home Manager is the preferred way to manage user environments. It allows declarative configuration of user-specific packages and files in the home directory. It is installed via the commands:

nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager

nix-channel --update
nix-shell '<home-manager>' -A install
home-manager edit

The command home-manager edit installs Home Manager, initializes and exposes the Home Manager configuration file located at .config/nixpkgs/home.nix.

Whenever something changes in the Home Manager configuration file, the command below builds and activates the configuration for the user.

Below is an edited version of the file home.nix to install the package firefox and to configure git.

 config, pkgs, ... :


  
  
  home.username = "florent";
  home.homeDirectory = "/home/florent";

  
  home.packages = [
    
    pkgs.firefox
  ];

  
  programs.git = 
    enable = true;
    userName = "Florent";
    userEmail = "[email protected]";
  ;

  
  
  
  
  
  
  
  
  home.stateVersion = "22.05";

  
  programs.home-manager.enable = true;

Note, alternative installation methods integrate Home Manager with the NixOS and nix-darwin configuration. This is how we deploy our systems. Follow the official documentation for more details.

Nix imperative operations: nix-env

User environment, including package installation and removal, can be managed with the nix-env commands. Below are some of the most useful commands:

nix-env -iA <nixpkgs.pkg-name>
  • To uninstall a package:

  • To upgrade a package:

    nix-env -u <some-packages>

Example: installation of virtualenv with Nix

Here are the steps to install the package virtualenv using the Nix package manager.

  • Search for virtualenv using the nix search command:

    nix search virtualenv
    warning: using cached results; pass '-u' to update the cache
    * nixpkgs.pew (pew-1.2.0)
    Tools to manage multiple virtualenvs written in pure python
    
    * nixpkgs.python38Packages.pytest-virtualenv (python3.8-pytest-virtualenv)
    Create a Python virtual environment in your test that cleans up on teardown. The fixture has utility methods to ins>
    
    * nixpkgs.python38Packages.tox (python3.8-tox-3.23.0)
    Virtualenv-based automation of test activities
    
    * nixpkgs.python38Packages.virtualenv (python3.8-virtualenv)
    A tool to create isolated Python environments
    
    * nixpkgs.python38Packages.virtualenv-clone (python3.8-virtualenv-clone)
    Script to clone virtualenvs
    
    * nixpkgs.python38Packages.virtualenvwrapper (python3.8-virtualenvwrapper)
    Enhancements to virtualenv
    
    * nixpkgs.python39Packages.pytest-virtualenv (python3.9-pytest-virtualenv)
    Create a Python virtual environment in your test that cleans up on teardown. The fixture has utility methods to ins>
    
    * nixpkgs.python39Packages.tox (python3.9-tox-3.23.0)
    Virtualenv-based automation of test activities
    
    * nixpkgs.python39Packages.virtualenv (python3.9-virtualenv)
    A tool to create isolated Python environments
    
    * nixpkgs.python39Packages.virtualenv-clone (python3.9-virtualenv-clone)
    Script to clone virtualenvs
    
    * nixpkgs.python39Packages.virtualenvwrapper (python3.9-virtualenvwrapper)
    Enhancements to virtualenv

    The search result offers several options to install virtualenv. We selected nixpkgs.python38Packages.virtualenv for the following commands.

  • Install nixpkgs.python38Packages.virtualenv

    • Option 1: using nix-env command:
    nix-env -iA nix-env -iA nixpkgs.python38Packages.virtualenv
    • Option 2: using Home Manager

      The content of the Home Manager configuration file includes:

       config, pkgs, ... :
      
         
        ...
        
        home.packages = [
          
          ...
          nixpkgs.python38Packages.virtualenv
          ...
        ];
        ...
      

      To apply the Home Manager configuration:

    virtualenv is installed. Below are the commands to create and activate a new python environment named myPythonEnv:

    virtualenv myPythonEnv 
    source myPythonEnv/bin/activate 

Generation

Every time a nix-env operation is done, a revision of the user environment called generation is newly created. Some commands associated to generation:

  • To list generations:

    nix-env --list-generations
  • To switch to a specific generation:

    nix-env --switch-generation <generation-number>
  • To remove specific generations:

    nix-env --delete-generations <generation-numbers separated by space>
  • To roll back to the last nix-env command (to the last generation):

  • To delete older generations:

    nix-env --delete-generations old

Profiles

Profiles are groups of generations so that different users don’t interfere with each other if they don’t want to. Profiles and User Environments are Nix’s mechanisms to allow different users to use different configurations.

Derivation

A Derivation is a Nix expression describing everything that goes into a package build action (build tools, dependencies, sources, build scripts, environment variables). It is anything needed to build up a package.

Channels

A channel is a git repository containing a list of packages. Official channels are verified by Nix. Some commands associated to channels:

Garbage collection

When a package is uninstalled, it is not actually deleted from the system even if no user refers to it. By this way, it won’t be re-downloaded if it happens that you need it again. Unsued packages are be deleted with the garbage collector command:

Conclusion

Nix is a cross-platform package manager managing dependencies by itself efficiently. It simplifies the process of managing a user environment via a declarative way and makes easy sharing of a user environment. However, it comes with a steep learning curve. In my experience, learning its usage was worth it.

Leave a Reply