Getting Started with Nix ======================== .. role:: bash(code) :language: bash 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. .. code-block:: text . ├── 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 make the usage of nix user-friendly, Nix proposes the user profiles, which can be described as a user environment, and the command `nix-env` enables to interact with the profiles. .. A profile is just a folder with a list of paths, which are packages currently installed. .. Once you have nix installed on your system, you can start by installing your first application. .. To start using Nix, and installing packages on your default profile you can type: To install a package on your default profile, you can type: .. code-block:: bash 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: .. code-block:: bash nix-env --query "*" You can remove an installed package from your current profile with: .. code-block:: bash 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): .. code-block:: bash nix-env --rollback Channels -------- .. _section-description-1: 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**. .. code-block:: bash nix-channel --list # 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 :bash:`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`. .. code-block:: bash # 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. .. code-block:: bash # 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. .. code-block:: bash # 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``: .. code-block:: bash 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: .. code-block:: bash 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: .. code-block:: bash nix-build '' -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``. .. code-block:: bash ./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. .. _apt: https://en.wikipedia.org/wiki/APT_(Package_Manager) .. _pacman: https://wiki.archlinux.org/index.php/pacman .. _git: https://en.wikipedia.org/wiki/Git .. _Nix's official profile documentation: https://nixos.org/nix/manual/#sec-profiles. .. _Nix pills about store paths: https://nixos.org/nixos/nix-pills/nix-store-paths.html .. _Nixpkgs source code: https://github.com/NixOS/nixpkgs .. _virtualenv: https://virtualenv.readthedocs.io/en/latest/ .. _Docker: https://en.wikipedia.org/wiki/Docker_(software) .. _Nix commands' cheatsheet: https://nixos.wiki/wiki/Cheatsheet .. _NixOS: https://nixos.org/ .. _Nixpkgs: https://github.com/NixOS/nixpkgs .. _NUR: https://github.com/nix-community/NUR