Getting Started with Nix

This section introduces basic Nix usage.

  • Install packages into the system through user profiles.
  • Manipulate and select channels.
  • Search for packages.

Nix vs traditional package managers

Installing a package with a traditional package manager (e.g., apt or pacman) involves several parts.

  • Getting the package content — either by downloading it from a cache or by rebuilding it.
  • Making the package available to the user.

These two parts are very close with the aforementioned package managers, as the way to make packages available to the user is to rely on some standard (or distribution-specific) directories. For example, executable files may be put into /usr/bin, libraries in /usr/lib and C include files in /usr/include.

The approach taken by Nix is different. Nix stores all packages into a common place called the Nix store, usually located at /nix/store. Each package is stored in a unique subdirectory in the store, and each package has its own tree structure. For example, a SimGrid package might be stored in /nix/store/l5rah62vpsr3ap63xmk197y0s1l6g2zx-simgrid-3.22.2. The package path is composed of a cryptographic hash of all the package inputs followed by the package name (more information about this can be found in Nix pills about store paths). The package file structure looks like the following.

.
├── bin
|   ├── smpicc
|   ├── smpirun
|   └── ...
├── include
│   └── ...
├── lib
│   ├── libsimgrid.so
│   └── ...
└── share
    └── ...

This storage system has very interesting properties, such as allowing the simultaneous presence of as many versions of a package as desired. However, it makes the “Making the package available to the user” more complex. Nix heavily relies on environment variables to make this possible. For example, an environment that contains the aforementioned SimGrid package and another hello package would put both /nix/store/l5rah62vpsr3ap63xmk197y0s1l6g2zx-simgrid-3.22.2/bin and /nix/store/06vykrz1hmxgxir8i74fwjl6r9bb2gpg-hello-2.10/bin into a $PATH environment variable. As managing such environment variables manually would be tedious, Nix propose many commands that manage them for you.

Profiles

Nix profiles are an abstraction that solves the “Making the package available to the user” issue discussed above. A profile describes an environment, that is to say a set of packages that are made available to the user. Managing profiles is mostly done with the nix-env command. Curious readers may be interested in Nix’s official profile documentation for an explanation about how profiles work internally.

To install a package on your default profile, you can type:

nix-env -i package_name

For instance, to install the fortune teller application, use nix-env -i fortune-mod.

To obtain the list of the packages installed in the current profile, you can use the command:

nix-env --query "*"

You can remove an installed package from your current profile with:

nix-env -e package_name

Warning

It is possible to remove several packages with a wildcard: nix-env -e "*". However, this command will also remove the package nix itself from the current profile. As a result, the current Nix profile will require a manual intervention to be recovered, as Nix commands will not be callable as usual.

A last profile feature worth mentioning here is the ability to go back to the previous generation (a new generation is created at each modification of the profile):

nix-env --rollback

Channels

The packages available in Nix are defined in a git repository that contains the definition of all the packages (see Nixpkgs source code). A channel, can be seen as a nixpkgs branch (as in git branch) that is validated by a continuous integration system. Several channels exists, the list of the currently available channels is available here.

Warning

In this section we introduce the channel fonctionnality of the Nix package manager as it is a convenient way to interact with the package manager, and it will give you a better understanding of what is happening under the hood.

However, using channels is not fully reproducible, as a channel may evolve to incorporate updates. When package reproducibility become a major concern, as it is the case in this tutorial, it is preferable to refer to a pinned version of the nixpkgs repository instead — i.e, a specific commit of the repository or an immutable archived tarball. The ability to pin the version of nixpkgs is powerful, it will ensure that a package is always constructed from the same Nix source. As we go deeper in the tutorial we avoid using channels in favor of pinned environments.

To list the channel currently installed on your system.

nix-channel --list
#<output> nixpkgs https://nixos.org/channels/nixpkgs-unstable

The command returns a name for each channel (e.g., nixpkgs) and an URL.

Note

When running nix-env with the parameter -A, one can select the channel to get the package from. Such a command looks like nix-env -iA channelname.packagename.

One can see that the default channel installed with Nix points to nixpkgs-unstable. Let us install a more stable channel instead. At the time of this tutorial (2022-06), the latest stable channel is nixpkgs-22.05.

# Add the channel 22.05 with the name nixpkgs.
nix-channel --add https://nixos.org/channels/nixos-22.05 nixpkgs
nix-channel --update

However, this had the effect to completely override the unstable channel. The unstable channel can be added back with another name.

# Add the unstable with the name `unstable`
nix-channel --add https://nixos.org/channels/nixpkgs-unstable unstable
nix-channel --update
# Check the result
nix-channel --list

Now that both channel are installed on your system, we can try installing packages from both of them.

# Installing Simgrid from the stable channel.
nix-env -iA nixpkgs.simgrid
# And installing it from unstable, this will override the current simgrid.
nix-env -iA unstable.simgrid

Utilities

Searching a package on Nixpkgs can be done via nix search:

nix search nixpkgs simgrid

Packages can also be searched on a web interface:

  • For nixpkgs (central repository of Nix packages used in the NixOS distribution: Nixpkgs)
  • For NUR (community-maintained distributed repositories of Nix packages: NUR)

Upgrading a package:

nix-env --upgrade simgrid

Build

nix-build can be used to build a package defined with the Nix Expression Language. For instance, building the hello package from the nixpkgs channel can be done like this:

nix-build '<nixpkgs>' -A hello

The resulting package is built and added to the nix store. For convenience, a link pointing to the package that has been put into the store is created in ./result.

./result/bin/hello

Shells

nix-shell enables to enter a shell in a controlled environment, or to run commands in such an environment. This is extremely powerful and convenient, and will be detailed in the next section of this tutorial. For now, you can see nix-shell as:

  • Python’s virtualenv on steroids, as it works with any programming language and can mix them.
  • Docker without isolation — just finely defined environment variables.

Other Commands

Many other Nix commands exist.

  • nix-collect-garbage cleans the Nix store of unused packages.
  • nix-store interacts with the nix store.
  • nix-copy-closure is convenient to synchronize parts of Nix store between several machines.

If you wonder how to do X with nix commands, the Nix commands’ cheatsheet can help you.