Linux is versatile and full of choices. Every other day you wake up to hear about a new distro. Most of these are based on a more famous distro and use its package manager. There are many package managers like Zypper and Yum for Red Hat-based systems; Aptitude and apt-get for Debian-based systems; and others like Pacman and Emerge. No matter how many package managers you have, you may still run into dependency hell or you may not be able to install multiple versions of the same package, especially for tinkering and testing. If you frequently mess up your system, you should try out Nix, which is more than just another package manager.
Nix is a purely functional package manager. According to its site, Nix is a powerful package manager for Linux and other UNIX systems that makes package management reliable and reproducible. It provides atomic upgrades and roll-backs, side-by-side installation of multiple versions of a package, multi-user package management and easy set-up of build environments. Here are some reasons for which the site recommends you ought to try Nix.
- Reliable: Nixs purely functional approach ensures that installing or upgrading one package cannot break other packages.
- Reproducible: Nix builds packages in isolation from each other. This ensures that they are reproducible and do not have undeclared dependencies. So if a package works on one machine, it will also work on another.
- Its great for developers: Nix makes it simple to set up and share build environments for your projects, regardless of what programming languages and tools youre using.
- Multi-user, multi-version: Nix supports multi-user package management. Multiple users can share a common Nix store securely without the need to have root privileges to install software, and can install and use different versions of a package.
- Source/binary model: Conceptually, Nix builds packages from source, but can transparently use binaries from a binary cache, if available.
- Portable: Nix runs on Linux, Mac OS X, FreeBSD and other systems. Nixpkgs, the Nix packages collection, contains thousands of packages, many pre-compiled.
Installation
Installation is pretty straightforward for Linux and Macs; everything is handled magically for you by a script, but there are some pre-requisites like sudo, curl and bash, so make sure you have them installed before moving on. Type the following command at a terminal:
bash <(curl https://nixos.org/nix/install)
It will ask for sudo access to create a directory named Nix. You may see something similar to whats shown in Figure 1.
There are binary packages available for Nix but we are looking for a new package manager, so using another package manager to install it is bad form (though you can, if you want to). If you are running another distro with no binary packages while also running Darwin or OpenBSD, you have the option of installing it from source. To set the environment variables right, use the following command:
./~/.nix-profile/etc/profile.d/nix.sh
Usage
Now that we have Nix installed, lets use it for further testing. To see a list of installable packages, run the following:
nix-env -qa
This will list the installable packages. To search for a specific package, pipe the output of the previous command to Grep with the name of the target package as the argument. Lets search for Ruby, with the following command:
nix-env -qa | grep ruby
It informs us that there are three versions of Ruby available. Lets install Ruby 2.0. There are two ways to install a package. Packages can be referred to by two identifiers. The first one is the name of the package, which might not be unique, and the second is the attribute set value. As the result of our search for the various Ruby versions showed that the name of the package for Ruby 2.0 is Ruby-2.0.0-p353, lets try to install it, as follows:
nix-env - i ruby-2.0.0-p353
It gives the following error as the output:
error: unable to fork: Cannot allocate memory nix-env: src/libutil/util.cc:766: int nix::Pid::wait(bool): Assertion `pid != -1 failed. Aborted (core dumped)
As per the Nix wiki, the name of the package might not be unique and may yield an error with some packages. So we could try things out with the attribute set value. For Ruby 2.0, the attribute set value is nixpkgs.ruby2 and can be used with the following command:
nix-env -iA nixpkgs.ruby2
This worked. Notice the use of -iA flag when using the attribute set value.
I talked to Nix developer Domen Koar about this and he said, Multiple packages may share the same name and version; thats why using attribute sets is a better idea, since it guarantees uniqueness. This is some kind of a downside of Nix, but this is how it functions :)
To see the attribute name and the package name, use the following command:
nix-env -qaP | grep package_name
In case of Ruby, I replaced the package_name with ruby2 and it yielded:
nixpkgs.ruby2 ruby-2.0.0-p353
To update a specific package and all its dependencies, use:
nix-env -uA nixpkgs.package_attribute_name
To update all the installed packages, use:
nix-env -u
To uninstall a package, use:
nix-env -e package_name
In my case, while using Ruby 2.0, I replaced it with Ruby-2.0.0-p353, which was the package name and not the attribute name.
Well, thats just the tip of the iceberg. To learn more, refer to the Nix manual http://nixos.org/nix/manual.
There is a distro named NixOS, which uses Nix for both configuration and package management.
References
[1] https://www.domenkozar.com/2014/01/02/getting-started-with-nix-package-manager/
[2] http://nixos.org/nix/manual/
[3] http://nixer.ghost.io/why/ – To convince yourself to use Nix