Package Management This chapter discusses how to do package management with Nix, i.e., how to obtain, install, upgrade, and erase components. This is the user's perspective of the Nix system — people who want to create components should consult . Basic package management The main command for package management is nix-env. You can use it to install, upgrade, and erase components, and to query what components are installed or are available for installation. In Nix, different users can have different views on the set of installed applications. That is, there might be lots of applications present on the system (possibly in many different versions), but users can have a specific selection of those active — where active just means that it appears in a directory in the user's PATH. Such a view on the set of installed applications is called a user environment, which is just a directory tree consisting of symlinks to the files of the active applications. Components are installed from a set of Nix expressions that tell Nix how to build those components, including, if necessary, their dependencies. There is a collection of Nix expressions called the Nix Package collection that contains components ranging from basic development stuff such as GCC and Glibc, to end-user applications like Mozilla Firefox. (Nix is however not tied to the Nix Package collection; you could write your own Nix expression based on that, or completely new.) You can download the latest version from . You probably want the latest unstable release; currently the stable releases tend to lag behind quite a bit. Assuming that you have downloaded and unpacked a release of Nix Packages, you can view the set of available components in the release: $ nix-env -qaf nixpkgs-version ant-blackdown-1.4.2 aterm-2.2 bash-3.0 binutils-2.15 bison-1.875d blackdown-1.4.2 bzip2-1.0.2 ... where nixpkgs-version is where you've unpacked the release. It is also possible to see the status of available component, i.e., whether they are installed into the user environment and/or present in the system: $ nix-env -qasf nixpkgs-version ... -PS bash-3.0 --S binutils-2.15 IPS bison-1.875d ... The first character (I) indicates whether the component is installed in your current user environment. The second (P) indicates whether it is present on your system (in which case installing it into your user environment would be very quick). The last one (S) indicates whether there is a so-called substitute for the component, which is Nix's mechanism for doing binary deployment. It just means that Nix know that it can fetch a pre-built component from somewhere (typically a network server) instead of building it locally. So now that we have a set of Nix expressions we can build the components contained in them. This is done using nix-env -i. For instance, $ nix-env -f nixpkgs-version -i subversion will install the component called subversion (which is, of course, the Subversion version management system). When you do this for the first time, Nix will start building Subversion and all its dependencies. This will take quite a while — typically an hour or two on modern machines. Fortunately, there is a faster way (so just do a Ctrl-C on that install operation!): you just need to tell Nix that pre-built binaries of all those components are available somewhere. This is done using the nix-pull command, which must be supplied with a URL containing a manifest describing what binaries are available. This URL should correspond to the Nix Packages release that you're using. For instance, if you obtained a release from , then you should do: $ nix-pull http://catamaran.labs.cs.uu.nl/dist/nix/nixpkgs-0.6pre1554/MANIFEST If you then issue the installation command, it should start downloading binaries from catamaran.labs.cs.uu.nl, instead of building them from source. This might still take a while since all dependencies must be downloaded, but on a reasonably fast connection such as an ADSL line it's on the order of a few minutes. Naturally, packages can also be uninstalled: $ nix-env -e subversion Upgrading to a new version is just as easy. If you have a new release of Nix Packages, you can do: $ nix-env -f nixpkgs-version -u subversion This will only upgrade Subversion if there is a newer version in the new set of Nix expressions, as defined by some pretty much arbitrary rules regarding ordering of version numbers (which generally do what you'd expect of them). To just unconditionally replace Subversion with whatever version is in the Nix expressions, use -i instead of -u; -i will remove whatever version is already installed. You can also upgrade all components for which there are newer versions: $ nix-env -f nixpkgs-version -u '*' Sometimes it's useful to be able to ask what nix-env would do, without actually doing it. For instance, to find out what packages would be upgraded by nix-env -u '*', you can do $ nix-env ... -u '*' --dry-run (dry run; not doing anything) upgrading `libxslt-1.1.0' to `libxslt-1.1.10' upgrading `graphviz-1.10' to `graphviz-1.12' upgrading `coreutils-5.0' to `coreutils-5.2.1' If you grow bored of specifying the Nix expressions using -f all the time, you can set a default location: $ nix-env -I nixpkgs-version After this you can just say, for instance, nix-env -u '*'.Setting a default using -I currently clashes with using Nix channels, since nix-channel --update calls nix-env -I to set the default to the Nix expressions it downloaded from the channel, replacing whatever default you had set. Profiles Profiles and user environments are Nix's mechanism for implementing the ability to allow differens users to have different configurations, and to do atomic upgrades and rollbacks. To understand how they work, it's useful to know a bit about how Nix works. In Nix, components are stored in unique locations in the Nix store (typically, /nix/store). For instance, a particular version of the Subversion component might be stored in a directory /nix/store/eeeeaf42e56b...-subversion-0.32.1/, while another version might be stored in /nix/store/58823d558a6a...-subversion-0.34/. The long hexadecimal numbers prefixed to the directory names are cryptographic hashes128 bit MD5 hashes, to be precise. of all inputs involved in building the component — sources, dependencies, compiler flags, and so on. So if two components differ in any way, they end up in different locations in the file system, so they don't interfere with each other. TODO: the figure isn't entirely up to date. It should show multiple profiles and ~/.nix-profile. shows a part of a typical Nix store.
User environments
Of course, you wouldn't want to type $ /nix/store/eeeeaf42e56b...-subversion-0.32.1/bin/svn every time you want to run Subversion. Of course we could set up the PATH environment variable to include the bin directory of every component we want to use, but this is not very convenient since changing PATH doesn't take effect for already existing processes. The solution Nix uses is to create directory trees of symlinks to activated components. These are called user environments and they are components themselves (though automatically generated by nix-env), so they too reside in the Nix store. For instance, in the user environment /nix/store/068150f63831...-user-env contains a symlink to just Subversion 0.32.1 (arrows in the figure indicate symlinks). This would be what we would obtain if we had done $ nix-env -i subversion on a set of Nix expressions that contained Subversion 0.32.1. This doesn't in itself solve the problem, of course; you wouldn't want to type /nix/store/068150f63831...-user-env/bin/svn either. Therefore there are symlinks outside of the store that point to the user environments in the store; for instance, the symlinks 42 and 43 in the example. These are called generations since every time you perform a nix-env operation, a new user environment is generated based on the current one. For instance, generation 43 was created from generation 42 when we did $ nix-env -i subversion mozilla on a set of Nix expressions that contained Mozilla and a new version of Subversion. Generations are grouped together into profiles so that different users don't interfere with each other if they don't want to. For example: $ ls -l /nix/var/nix/profiles/ ... lrwxrwxrwx 1 eelco ... default-42-link -> /nix/store/068150f63831...-user-env lrwxrwxrwx 1 eelco ... default-43-link -> /nix/store/84c85f89ddbf...-user-env lrwxrwxrwx 1 eelco ... default -> default-43-link This shows a profile called default. The file default itself is actually a symlink that point to the current generation. When we do a nix-env operation, a new user environment and generation link are created based on the current one, and finally the default symlink is made to point at the new generation. This last step is atomic on Unix, which explains how we can do atomic upgrades. (Note that the building/installing of new components doesn't interfere in any way with old components, since they are stored in different locations in the Nix store.) If you find that you want to undo a nix-env operation, you can just do $ nix-env --rollback which will just make the current generation link point at the previous link. E.g., default would be made to point at default-42-link. You can also switch to a specific generation: $ nix-env --switch-generation 43 which in this example would roll forward to generation 43 again. You can also see all available generations: $ nix-env --list-generations Actually, there is another level of indirection not shown in the figure above. You generally wouldn't have /nix/var/nix/profiles/some-profile/bin in your PATH. Rather, there is a symlink ~/.nix-profile that point to your current profile. This means that you should put ~/.nix-profile/bin in your PATH (and indeed, that's what the initialisation script /nix/etc/profile.d/nix.sh does). This makes it easier to switch to a different profile, which is exactly what the command nix-env --switch-profile does: $ nix-env --switch-profile /nix/var/nix/profiles/my-profile $ nix-env --switch-profile /nix/var/nix/profiles/default These commands switch to the my-profile and default profile, respectively. If the profile doesn't exist, it will be created automatically. You should be careful about storing a profile in another location that the profiles directory, since otherwise it might not be used as a root to the garbage collection (see section ). All nix-env operations work on the profile pointed to by ~/.nix-profile, but you can override this on using the option (abbreviation ): $ nix-env -p /nix/var/nix/profiles/other-profile -i subversion This will not change the ~/.nix-profile symlink.
Garbage collection nix-env operations such as upgrades () and uninstall () never actually delete components from the system. All they do (as shown above) is to make a new user environment that no longer contains symlinks to the deleted components. Of course, since disk space is not infinite, unused components should be removed at some point. You can do this by running the Nix garbage collector. It will remove from the Nix store any component not used (directly or indirectly) by any generation of any profile. Note however that as long as old generations reference a component, it will not be deleted. After all, we wouldn't be able to do a rollback otherwise. So in order for garbage collection to be effective, you should also delete (some) old generations. Of course, this should only be done if you are certain that you will not need to roll back. To delete all old (non-current) generations of your current profile: $ nix-env --delete-generations old Instead of old you can also specify a list of generations, e.g., $ nix-env --delete-generations 10 11 14 After removing appropriate old generations you can run the garbage collector as follows: $ nix-collect-garbage You can alo first view what files would be deleted: $ nix-collect-garbage --print-dead Likewise, the option will show the paths that won't be deleted. Garbage collector roots TODO The garbage collector uses as roots all store expressions mentioned in all files with extension .gcroot in the directory prefix/var/nix/gcroots/, or in any file or directory symlinked to from that directory. E.g., by default, prefix/var/nix/gcroots/ contains a symlink to prefix/var/nix/profiles/, so all generations of all profiles are also roots of the collector. Channels TODO