Nix: A System for Software Deployment

Draft (Version 0.5)

Eelco Dolstra


Table of Contents

1. Introduction
2. Quick Start
3. Installation
3.1. Obtaining Nix
3.2. Prerequisites
3.3. Building Nix from source
3.4. Installing from RPMs
3.5. Permissions
3.6. Using Nix
4. Overview
4.1. Basic package management
4.2. Writing Nix expressions
4.2.1. A simple Nix expression
4.2.2. A more complex Nix expression
A. Command Reference
A.1. nix-env
A.2. nix-store
A.3. nix-instantiate
A.4. nix-collect-garbage
A.5. nix-push
A.6. nix-pull
A.7. nix-prefetch-url
5. Nix Language Reference
5.1. Grammar
5.2. Semantics
5.2.1. Built-in functions
B. Troubleshooting
C. Bugs / To-Do

List of Examples

4.1. Nix expression for GNU Hello
4.2. Build script (builder.sh) for GNU Hello
4.3. Nix expression for Subversion

Chapter 1. Introduction

The number of Nix installations in the world has grown to 5, with more expected.

Nix is a system for software deployment. It supports the creation and distribution of software packages, as well as the installation and subsequent management of these on target machines (i.e., it is also a package manager).

Nix solves some large problems that exist in most current deployment and package management systems. Dependency determination is a big one: the correct installation of a software component requires that all dependencies of that component (i.e., other components used by it) are also installed. Most systems have no way to verify that the specified dependencies of a component are actually sufficient.

Another big problem is the lack of support for concurrent availability of multiple variants of a component. It must be possible to have several versions of a component installed at the same time, or several instances of the same version built with different parameters. Unfortunately, components are in general not properly isolated from each other. For instance, upgrading a component that is a dependency for some other component might break the latter.

Nix solves these problems by building and storing packages in paths that are infeasible to predict in advance. For example, the artifacts of a package X might be stored in /nix/store/d58a0606ed616820de291d594602665d-X, rather than in, say, /usr/lib. The path component d58a... is actually a cryptographic hash of all the inputs (i.e., sources, requisites, and build flags) used in building X, and as such is very fragile: any change to the inputs will change the hash. Therefore it is not sensible to hard-code such a path into the build scripts of a package Y that uses X (as does happen with “fixed” paths such as /usr/lib). Rather, the build script of package Y is parameterised with the actual location of X, which is supplied by the Nix system.

As stated above, the path name of a file system object contain a cryptographic hash of all inputs involved in building it. A change to any of the inputs will cause the hash to change--and by extension, the path name. These inputs include both sources (variation in time) and configuration options (variation in space). Therefore variants of the same package don't clash---they can co-exist peacefully within the same file system.

Other features:

Transparent source/binary deployment.

Unambiguous identification of configuration.

Automatic storage management.

Atomic upgrades and rollbacks.

Support for many simultaneous configurations.

Portability. Nix is quite portable. Contrary to build systems like those in, e.g., Vesta and ClearCase, it does not rely on operating system extensions.

Chapter 2. Quick Start

This chapter is for impatient people who don't like reading documentation. For more in-depth information you are kindly referred to Chapter 3, Installation and Chapter 4, Overview.

  1. Download a source tarball or RPM from http://www.cs.uu.nl/groups/ST/Trace/Nix. Build source distributions using the regular sequence:

    $ tar xvfj nix-version.tar.bz2
    $ ./configure
    $ make
    $ make install (as root)

    This will install Nix in /nix. You should also add /nix/etc/profile.d/nix.sh to your ~/.bashrc (or some other login file).

  2. Get some Nix expressions for pre-built packages by downloading the latest nixpkgs distribution (from the same location), and unpack them.

    $ wget http://.../nix/nixpkgs-version/nixpkgs-version.tar.bz2
    $ tar xfj nixpkgs-version.tar.bz2

    This will unpack the distribution into a directory nixpkgs-version/.

  3. Pull the Nix cache. This ensures that when you install packages they are downloaded in pre-built form from the network, rather than built from source.

    $ nix-pull http://.../nix/nixpkgs-version/MANIFEST

    Note that currently we only pre-build for Linux on x86 platforms.

  4. See what's available:

    $ nix-env -qaf nixpkgs-version/
    MozillaFirebird-0.7
    hello-2.1.1
    docbook-xml-4.2
    libxslt-1.1.0
    ...

  5. Install some packages:

    $ nix-env -iBf nixpkgs-version/ hello MozillaFirebird ... 

  6. Test that they work:

    $ which hello
    /home/eelco/.nix-profile/bin/hello
    $ hello
    Hello, world!
    $ MozillaFirebird
    (read Slashdot or something)

  7. Uninstall a package:

    $ nix-env -e hello

  8. If a new release of nixpkgs comes along, you can upgrade all installed packages to the latest versions by downloading and unpacking the new release and doing:

    $ nix-env -uBf nixpkgs-version/ '*'

  9. You should periodically run the Nix garbage collector to get rid of unused packages, since uninstalls or upgrades don't actual delete them:

    $ nix-collect-garbage | xargs nix-store --delete

Chapter 3. Installation

3.1. Obtaining Nix

The easiest way to obtain Nix is to download a source distribution. RPMs for SuSE and Red Hat are also available. These distributions are generated automatically.

Alternatively, the most recent sources of Nix can be obtained from its Subversion repository. For example, the following command will check out the latest revision into a directory called nix:

$ svn checkout https://svn.cs.uu.nl:12443/repos/trace/nix/trunk nix

Likewise, specific releases can be obtained from the tags directory of the repository. If you don't have Subversion, you can also download an automatically generated compressed tar-file of the head revision of the trunk.

3.2. Prerequisites

The following prerequisites only apply when you build from source. Binary releases (e.g., RPMs) have no prerequisites.

A fairly recent version of GCC/G++ is required. Version 2.95 and higher should work.

To build this manual and the man-pages you need the xmllint and xsltproc programs, which are part of the libxml2 and libxslt packages, respectively. You also need the DocBook XSL stylesheets and optionally the DocBook XML 4.2 DTD. Note that these are only required if you modify the manual sources or when you are building from the Subversion repository.

To build the parser, very recent versions of Bison and Flex are required. (This is because Nix needs GLR support in Bison and reentrancy support in Flex.) For Bison, you need version 1.875c or higher (1.875 does not work), which can be obtained from the GNU FTP server. For Flex, you need version 2.5.31, which is available on SourceForge. Slightly older versions may also work, but ancient versions like the ubiquitous 2.5.4a won't. Note that these are only required if you modify the parser or when you are building from the Subversion repository.

Nix uses Sleepycat's Berkeley DB and CWI's ATerm library. These are included in the Nix source distribution. If you build from the Subversion repository, you must download them yourself and place them in the externals/ directory. See externals/Makefile.am for the precise URLs of these packages.

3.3. Building Nix from source

After unpacking or checking out the Nix sources, issue the following commands:

$ ./configure options...
$ make
$ make install

When building from the Subversion repository, these should be preceded by the command:

$ autoreconf -i

The installation path can be specified by passing the --prefix=prefix to configure. The default installation directory is /nix. You can change this to any location you like. You must have write permission to the prefix path.

Warning

It is advisable not to change the installation prefix from its default, since doing so will in all likelihood make it impossible to use derivations built on other systems.

If you want to rebuilt the documentation, pass the full path to the DocBook XML catalog file (docbook.cat) and to the DocBook XSL stylesheets using the --with-docbook-catalog=path and --with-docbook-xsl=path options.

3.4. Installing from RPMs

RPM packages of Nix can be downloaded from http://www.cs.uu.nl/groups/ST/Trace/Nix. These RPMs should work for most fairly recent releases of SuSE and Red Hat Linux. They have been known to work work on SuSE Linux 8.1 and 9.0, and Red Hat 9.0. In fact, it should work on any RPM-based Linux distribution based on glibc 2.3 or later.

Once downloaded, the RPMs can be installed or upgraded using rpm -U. For example,

rpm -U nix-0.5pre664-1.i386.rpm

The RPMs install into the directory /nix. Nix can be uninstalled using rpm -e nix. After this it will be necessary to manually remove the Nix store and other auxiliary data:

rm -rf /nix/store
rm -rf /nix/var

3.5. Permissions

All Nix operations must be performed under the user ID that owns the Nix store and database (prefix/store and prefix/var/nix/db, respectively). When installed from the RPM packages, these directories are owned by root.

3.6. Using Nix

To use Nix, some environment variables should be set. In particular, PATH should contain the directories prefix/bin and ~/.nix-profile/bin. The first directory contains the Nix tools themselves, while ~/.nix-profile is a symbolic link to the current user environment (an automatically generated package consisting of symlinks to installed packages). The simplest way to set the required environment variables is to include the file prefix/etc/profile.d/nix.sh in your ~/.bashrc (or similar), like this:

. prefix/etc/profile.d/nix.sh

Chapter 4. Overview

This chapter provides a guided tour of Nix.

4.1. Basic package management

Let's start from the perspective of an end user. Common operations at this level are to install and remove packages, ask what packages are installed or available for installation, and so on. These are operations on the user environment: the set of packages that a user “sees”. In a command line Unix environment, this means the set of programs that are available through the PATH environment variable. (In other environments it might mean the set of programs available on the desktop, through the start menu, and so on.)

The terms “installation” and “uninstallation” are used in this context to denote the act of adding or removing packages from the user environment. In Nix, these operations are dissociated from the physical copying or deleting of files. Installation requires that the files constituting the package are present, but they may be present beforehand. Likewise, uninstallation does not actually delete any files; this is done automatically by running a garbage collector.

User environments are manipulated through the nix-env command. The query operation can be used to see what packages are currently installed.

$ nix-env -q
MozillaFirebird-0.7
sylpheed-0.9.7
pan-0.14.2

(-q is actually short for --query --installed.) The package names are symbolic: they don't have any particular significance to Nix (as they shouldn't, since they are not unique—there can be many derivations with the same name). Note that these packages have many dependencies (e.g., Mozilla uses the gtk+ package) but these have not been installed in the user environment, though they are present on the system. Generally, there is no need to install such packages; only packages containing programs should be installed.

To install packages, a Nix expression is required that tells Nix how to build that package. There is a set of standard of Nix expressions for many common packages. Assuming that you have downloaded and unpacked these, you can view the set of available packages:

$ nix-env -qaf pkgs/system/i686-linux.nix
gettext-0.12.1
sylpheed-0.9.7
aterm-2.0
gtk+-1.2.10
apache-httpd-2.0.48
pan-0.14.2
...

The Nix expression in the file i686-linux.nix yields the set of packages for a Linux system running on x86 hardware. For other platforms, copy and modify this file for your platform as appropriate. [TODO: improve this]

It is also possible to see the status of available packages, i.e., whether they are installed into the user environment and/or present in the system:

$ nix-env -qasf pkgs/system/i686-linux.nix
-P gettext-0.12.1
IP sylpheed-0.9.7
-- aterm-2.0
-P gtk+-1.2.10

This reveals that the sylpheed package is already installed, or more precisely, that exactly the same instantiation of sylpheed is installed. This guarantees that the available package is exactly the same as the installed package with regard to sources, dependencies, build flags, and so on. Similarly, we see that the gettext and gtk+ packages are present but not installed in the user environment, while the aterm package is not installed or present at all (so, if we were to install it, it would have to be built or downloaded first).

The install operation is used install available packages from a Nix environment. To install the pan package (a newsreader), you would do:

$ nix-env -if pkgs/system/i686-linux.nix pan

Since installation may take a long time, depending on whether any packages need to be built or downloaded, it's a good idea to make nix-env run verbosely by using the -v (--verbose) option. This option may be repeated to increase the level of verbosity. A good value is 3 (-vvv).

In fact, if you run this command verbosely you will observe that Nix starts to build many packages, including large and fundamental ones such as glibc and gcc. I.e., you are performing a source installation. This is generally undesirable, since installation from sources may require large amounts of disk and CPU resources. Therefore a “binary” installation is generally preferable.

Rather than provide different mechanisms to create and perform the installation of binary packages, Nix supports binary deployment transparently through a generic mechanism of substitute expressions. If an request is made to build some Nix expression, Nix will first try to build any substitutes for that expression. These substitutes presumably perform an identical build operation with respect to the result, but require less resources. For instance, a substitute that downloads a pre-built package from the network requires less CPU and disk resources, and possibly less time.

Nix's use of cryptographic hashes makes this entirely safe. It is not possible, for instance, to accidentally substitute a build of some package for a Solaris or Windows system for a build on a SuSE/x86 system.

While the substitute mechanism is a generic mechanism, Nix provides two standard tools called nix-pull and nix-push that maintain and use a shared cache of prebuilt derivations on some network site (reachable through HTTP). If you attempt to install some package that someone else has previously built and “pushed” into the cache, and you have done a “pull” to register substitutes that download these prebuilt packages, then the installation will automatically use these.

For example, to pull from our cache of prebuilt packages (at the time of writing, for SuSE Linux/x86), use the following command:

$ nix-pull http://catamaran.labs.cs.uu.nl/dist/nix/nixpkgs-version/MANIFEST
obtaining list of Nix archives at http://catamaran.labs.cs.uu.nl/dist/nix/nixpkgs-version/MANIFEST...
...

If nix-pull is run without any arguments, it will pull from the URLs specified in the file prefix/etc/nix/prebuilts.conf.

Assuming that the pan installation produced no errors, it can be used immediately, that is, it now appears in a directory in the PATH environment variable. Specifically, PATH includes the entry prefix/var/nix/profiles/default/bin, where prefix/var/nix/profiles/default is just a symlink to the current user environment:

$ ls -l /nix/var/nix/profiles/
...
lrwxrwxrwx  1 eelco ... default-15-link -> /nix/store/1871...12b0-user-environment
lrwxrwxrwx  1 eelco ... default-16-link -> /nix/store/59ba...df6b-user-environment
lrwxrwxrwx  1 eelco ... default -> default-16-link

That is, default in this example is a link to default-16-link, which is the current user environment. Before the installation, it pointed to default-15-link. Note that this means that you can atomically roll-back to the previous user environment by pointing the symlink default at default-15-link again. This also shows that operations such as installation are atomic in the Nix system: any arbitrarily complex set of installation, uninstallation, or upgrade actions eventually boil down to the single operation of pointing a symlink somewhere else (which can be implemented atomically in Unix).

What's in a user environment? It's just a set of symlinks to the files that constitute the installed packages. For instance:

$ ls -l /nix/var/nix/profiles/default-16-link/bin
lrwxrwxrwx  1 eelco ... MozillaFirebird -> /nix/store/35f8...4ae6-MozillaFirebird-0.7/bin/MozillaFirebird
lrwxrwxrwx  1 eelco ... svn -> /nix/store/3829...fb5d-subversion-0.32.1/bin/svn
...

Note that, e.g., svn = /nix/var/nix/profiles/default/bin/svn = /nix/var/nix/profiles/default-16-link/bin/svn = /nix/store/59ba...df6b-user-environment/bin/svn = /nix/store/3829...fb5d-subversion-0.32.1/bin/svn.

Naturally, packages can also be uninstalled:

$ nix-env -e pan

This means that the package is removed from the user environment. It is not yet removed from the system. When a package is uninstalled from a user environment, it may still be used by other packages, or may still be present in other user environments. Deleting it under such conditions would break those other packages or user environments. To prevent this, packages are only “physically” deleted by running the Nix garbage collector, which searches for all packages in the Nix store that are no longer “reachable” from outside the store. Thus, uninstalling a package is always safe: it cannot break other packages.

Upgrading packages is easy. Given a Nix expression that contains newer versions of installed packages (that is, packages with the same package name, but a higher version number), nix-env -u will replace the installed package in the user environment with the newer package. For example,

$ nix-env -uf pkgs/system/i686-linux.nix pan

looks for a newer version of Pan, and installs it if found. Also useful is the ability to upgrade all packages:

$ nix-env -uf pkgs/system/i686-linux.nix '*'

The asterisk matches all installed packages[1]. Note that * must be quoted to prevent shell globbing.

4.2. Writing Nix expressions

4.2.1. A simple Nix expression

This section shows how to write simple Nix expressions—the things that describe how to build a package.

Example 4.1. Nix expression for GNU Hello

{stdenv, fetchurl, perl}: 1

derivation { 2
  name = "hello-2.1.1"; 3
  system = stdenv.system; 4
  builder = ./builder.sh; 5
  src = fetchurl { 6
    url = ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz;
    md5 = "70c9ccf9fac07f762c24f2df2290784d";
  };
  stdenv = stdenv; 7
  perl = perl;
}

A simple Nix expression is shown in Example 4.1, “Nix expression for GNU Hello”. It describes how to the build the GNU Hello package. This package has several dependencies. First, it requires a number of other packages, such as a C compiler, standard Unix shell tools, and Perl. Rather than have this Nix expression refer to and use specific versions of these packages, it should be generic; that is, it should be a function that takes the required packages as inputs and yield a build of the GNU Hello package as a result. This Nix expression defines a function with three arguments 1, namely:

  1. stdenv, which should be a standard environment package. The standard environment is a set of tools and other components that would be expected in a fairly minimal Unix-like environment: a C compiler and linker, Unix shell tools, and so on.

  2. fetchurl, which should be a function that given parameters url and md5, will fetch a file from the specified location and check that this file has the given MD5 hash code. The hash is required because build operations must be pure: given the same inputs they should always yield the same output. Since network resources can change at any time, we must in some way guarantee what the result will be.

  3. perl, which should be a Perl interpreter.

The remainder of the file is the body of the function, which happens to be a derivation 2, which is the built-in function derivation applied to a set of attributes that encode all the necessary information for building the GNU Hello package.

Example 4.2. Build script (builder.sh) for GNU Hello

#! /bin/sh

buildinputs="$perl"
. $stdenv/setup || exit 1

tar xvfz $src || exit 1
cd hello-* || exit 1
./configure --prefix=$out || exit 1
make || exit 1
make install || exit 1

4.2.2. A more complex Nix expression

Example 4.3. Nix expression for Subversion

{ localServer ? false 1
, httpServer ? false
, sslSupport ? false
, swigBindings ? false
, stdenv, fetchurl
, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null
}:

assert !isNull expat; 2
assert localServer -> !isNull db4;
assert httpServer -> !isNull httpd && httpd.expat == expat; 3
assert sslSupport -> !isNull openssl && (httpServer -> httpd.openssl == openssl);
assert swigBindings -> !isNull swig;

derivation {
  name = "subversion-0.32.1";
  system = stdenv.system;

  builder = ./builder.sh;
  src = fetchurl {
    url = http://svn.collab.net/tarballs/subversion-0.32.1.tar.gz;
    md5 = "b06717a8ef50db4b5c4d380af00bd901";
  };

  localServer = localServer;
  httpServer = httpServer;
  sslSupport = sslSupport;
  swigBindings = swigBindings;

  stdenv = stdenv;
  openssl = if sslSupport then openssl else null; 4
  httpd = if httpServer then httpd else null;
  expat = expat;
  db4 = if localServer then db4 else null;
  swig = if swigBindings then swig else null;
}

This example shows several features. Default parameters 1 can be used to simplify call sites: if an argument that has a default is omitted, its default value is used.

You can use assertions to test whether arguments satisfy certain constraints. The simple assertion 2 tests whether the expat argument is not a null value. The more complex assertion 3 says that if Subversion is built with Apache support, then httpd (the Apache package) must not be null and it must have been built using the same instance of the expat library as was passed to the Subversion expression. This is since the Subversion code is dynamically linked against the Apache code and they both use Expat, they must be linked against the same instance—otherwise a conflict might occur.



[1] No, we don't support arbitrary regular expressions

Appendix A. Command Reference

A.1. nix-env

Name

nix-env — manipulate or query Nix user environments

Synopsis

nix-env [--help] [--version] [--verbose...] [-v...] [--build-output] [-B] [--keep-failed] [-K] [ { --file | -f } path ] [ { --profile | -p } path ] [--dry-run] operation [options...] [arguments...]

Description

The command nix-env is used to manipulate Nix user environments. User environments are sets of software components available to a user at some point in time. In other words, they are a synthesised view of the programs available in the Nix store. There may be many user environments: different users can have different environments, and individual users can switch between different environments.

nix-env takes exactly one operation flag which indicates the subcommand to be performed. These are documented below.

Common options

This section lists the options that are common to all operations. These options are allowed for every subcommand, though they may not always have an effect.

--help

Prints out a summary of the command syntax and exits.

--version

Prints out the Nix version number on standard output and exits.

--verbose / -v

Increases the level of verbosity of diagnostic messages printed on standard error. For each Nix operation, the information printed on standard output is well-defined; any diagnostic information is printed on standard error, never on standard output.

This option may be specified repeatedly. Currently, the following verbosity levels exist:

0

Errors only”: only print messages explaining why the Nix invocation failed.

1

Informational”: print useful messages about what Nix is doing.

2

Talkative”: print more informational messages.

3

Chatty”: print even more informational messages.

4

Debug”: print debug information:

5

Vomit”: print vast amounts of debug information.

--build-output / -B

Causes the output written by build actions to standard output and standard error to be echoed to standard error, regardless of verbosity level. By default, it is only echoed at a verbosity level of at least 4 (“Debug”), and is suppressed at lower levels. Note that it is always written to a log file in prefix/nix/var/log/nix.

--keep-failed / -K

Specifies that in case of a build failure, the temporary directory (usually in /tmp) in which the build takes place should not be deleted. The path of the build directory is printed as an informational message.

--file / -f

Specifies the Nix expression (designated below as the active Nix expression) used by the --install, --upgrade, and --query --available operations to obtain derivations. The default is ~/.nix-defexpr.

--profile / -p

Specifies the profile to be used by those operations that operate on a profile (designated below as the active profile). A profile is sequence of user environments called generations, one of which is the current generation. The default profile is the target of the symbolic link ~/.nix-profile (see below).

--dry-run

For the --install, --upgrade, --uninstall, --switch-generation and --rollback operations, this flag will cause nix-env to print what would be done if this flag had not been specified, without actually doing it.

Files

~/.nix-defexpr

The default Nix expression used by the --install, --upgrade, and --query --available operations to obtain derivations. It is generally a symbolic link to some other location set using the --import operation. The --file option may be used to override this default.

~/.nix-profile

A symbolic link to the user's current profile. By default, this symlink points to prefix/var/nix/profiles/default. The PATH environment variable should include ~/.nix-profile/bin for the user environment to be visible to the user.

Operation --install

Synopsis

nix-env { --install | -i } drvnames...

Description

The install operation creates a new user environment, based on the current generation of the active profile, to which the derivations designated by drvnames in the active Nix expression are added.

Examples

$ nix-env --install gcc-3.3.2 (install specific version)
$ nix-env --install gcc (just pick any version)
$ nix-env -f ~/foo.nix -i '*' (install everything in foo.nix)

Operation --upgrade

Synopsis

nix-env { --upgrade | -u } [ --lt | --leq | --always ] drvnames...

Description

The upgrade operation creates a new user environment, based on the current generation of the active profile, in which all derivations designated by drvnames for which there are newer versions in the active Nix expression are replaced by those newer versions. Matching derivations for which there are no newer versions are left untouched; this is not an error. It is also not an error if an element of drvnames matches no installed derivations.

If multiple derivations in the active Nix expression match an installed derivation, the one with the highest version is selected.

Flags

--lt

Only upgrade a derivation to newer versions. This is the default.

--leq

In addition to upgrading to newer versions, also “upgrade” to derivations that have the same version. Version are not a unique identification of a derivation, so there may be many derivations that have the same version. This flag may be useful to force “synchronisation” between the installed and available derivations.

--always

In addition to upgrading to newer versions, also “upgrade” to derivations that have the same or a lower version. I.e., derivations may actually be downgraded depending on what is available in the active Nix expression.

Examples

$ nix-env --upgrade gcc
upgrading `gcc-3.3.1' to `gcc-3.4'

$ nix-env --upgrade pan
(no upgrades available, so nothing happens)

$ nix-env -u '*' (try to upgrade everything)
upgrading `hello-2.1.2' to `hello-2.1.3'
upgrading `mozilla-1.2' to `mozilla-1.4'

Versions

The upgrade operation determines whether a derivation y is an upgrade of a derivation x by looking at their respective name attributes. The names (e.g., gcc-3.3.1 are split into two parts: the package name (gcc), and the version (3.3.1). The version part starts after the first dash not following by a letter. x is considered an upgrade of y if their package names match, and the version of y is higher that that of x.

The versions are compared by splitting them into contiguous components of numbers and letters. E.g., 3.3.1pre5 is split into [3, 3, 1, "pre", 5]. These lists are then compared lexicographically (from left to right). Corresponding components a and b are compared as follows. If they are both numbers, integer comparison is used. If a is an empty string and b is a number, a is considered less than b. The special string component pre (for pre-release) is considered to be less than other components. String components are considered less than number components. Otherwise, they are compared lexicographically (i.e., using case-sensitive string comparison).

This is illustrated by the following examples:

1.0 < 2.3
2.1 < 2.3
2.3 = 2.3
2.5 > 2.3
3.1 > 2.3
2.3.1 > 2.3
2.3.1 > 2.3a
2.3pre1 < 2.3
2.3pre3 < 2.3pre12
2.3a < 2.3c
2.3pre1 < 2.3c
2.3pre1 < 2.3q

Operation --uninstall

Synopsis

nix-env { --uninstall | -e } drvnames...

Description

The uninstall operation creates a new user environment, based on the current generation of the active profile, from which the derivations designated by drvnames are removed.

Examples

$ nix-env --uninstall gcc
$ nix-env -e '*' (remove everything)

Operation --query

Synopsis

nix-env { --query | -q } [ --installed | --available | -a ] { --name | --expr | --status | -s }

Description

The query operation displays information about either the derivations that are installed in the current generation of the active profile (--installed), or the derivations that are available for installation in the active Nix expression (--available).

The derivations are sorted by their name attributes.

Source selection

The following flags specify the set of derivations on which the query operates.

--installed

The query operates on the derivations that are installed in the current generation of the active profile. This is the default

--available / -a

The query operates on the derivations that are available in the active Nix expression.

Queries

The following flags specify what information to display about the selected derivations. Only one type of query may be specified.

--name

Prints the name attribute of each derivation. This is the default.

--expr

Prints the store expression in the Nix store that described the derivation.

--status / -s

Prints the status of each derivation, followed by its name attribute. The status consists of three characters. The first is I or -, indicating whether the derivation is currently installed in the current generation of the active profile. This is by definition the case for --installed, but not for --available. The second is P or -, indicating whether the derivation is present on the system. This indicates whether installation of an available derivation will require the derivation to be built. The third is S or -, indicating whether a substitute is available for the derivation.

Examples

$ nix-env -q (show installed derivations)
MozillaFirebird-0.7
bison-1.875c
docbook-xml-4.2
...

$ nix-env -qa (show available derivations)
GConf-2.4.0.1
MPlayer-1.0pre3
MozillaFirebird-0.7
ORBit2-2.8.3
...

$ nix-env -qas (show status of available derivations)
-P- GConf-2.4.0.1 (not installed but present)
--S MPlayer-1.0pre3 (not present, but there is a substitute for fast installation)
--S MozillaFirebird-0.7 (i.e., this is not the installed Firebird, even though the version is the same!)
IP- bison-1.875c (installed and by definition present)
...

$ nix-env -f ./foo.nix -qa (show available derivations in the Nix expression foo.nix)
foo-1.2.3

Operation --switch-profile

Synopsis

nix-env { --switch-profile | -S } {path}

Description

This operation makes path the current profile for the user. That is, the symlink ~/.nix-profile is made to point to path.

Examples

$ nix-env -S ~/my-profile

Operation --list-generations

Synopsis

nix-env {--list-generations}

Description

This operation print a list of all the currently existing generations for the active profile. These may be switched to using the --switch-generation operation. It also prints the creation date of the generation, and indicates the current generation.

Examples

$ nix-env --list-generations
  95   2004-02-06 11:48:24
  96   2004-02-06 11:49:01
  97   2004-02-06 16:22:45
  98   2004-02-06 16:24:33   (current)

Operation --switch-generation

Synopsis

nix-env { --switch-generation | -G } {generation}

Description

This operation makes generation number generation the current generation of the active profile. That is, if the profile is the path to the active profile, then the symlink profile is made to point to profile-generation-link, which is in turn a symlink to the actual user environment in the Nix store.

Switching will fail if the specified generation does not exist.

Examples

$ nix-env -G 42
switching from generation 50 to 42

Operation --rollback

Synopsis

nix-env {--rollback}

Description

This operation switches to the “previous” generation of the active profile, that is, the highest numbered generation lower than the current generation, if it exists. It is just a convenience wrapper around --list-generations and --switch-generation.

Examples

$ nix-env --rollback
switching from generation 92 to 91

$ nix-env --rolback
error: no generation older than the current (91) exists

Operation --import

Synopsis

nix-env { --import | -I } {path}

Description

This operation makes path the default active Nix expression for the user. That is, the symlink ~/.nix-userenv is made to point to path.

Examples

$ nix-env -I ~/nixpkgs-0.5/

A.2. nix-store

Name

nix-store — manipulate or query the Nix store

Synopsis

nix-store [--help] [--version] [--verbose...] [-v...] [--build-output] [-B] [--keep-failed] [-K] operation [options...] [arguments...]

Description

The command nix-store performs primitive operations on the Nix store. You generally do not need to run this command manually.

nix-store takes exactly one operation flag which indicates the subcommand to be performed. These are documented below.

Common options

This section lists the options that are common to all operations. These options are allowed for every subcommand, though they may not always have an effect.

--help

Prints out a summary of the command syntax and exits.

--version

Prints out the Nix version number on standard output and exits.

--verbose / -v

Increases the level of verbosity of diagnostic messages printed on standard error. For each Nix operation, the information printed on standard output is well-defined; any diagnostic information is printed on standard error, never on standard output.

This option may be specified repeatedly. Currently, the following verbosity levels exist:

0

Errors only”: only print messages explaining why the Nix invocation failed.

1

Informational”: print useful messages about what Nix is doing.

2

Talkative”: print more informational messages.

3

Chatty”: print even more informational messages.

4

Debug”: print debug information:

5

Vomit”: print vast amounts of debug information.

--build-output / -B

Causes the output written by build actions to standard output and standard error to be echoed to standard error, regardless of verbosity level. By default, it is only echoed at a verbosity level of at least 4 (“Debug”), and is suppressed at lower levels. Note that it is always written to a log file in prefix/nix/var/log/nix.

--keep-failed / -K

Specifies that in case of a build failure, the temporary directory (usually in /tmp) in which the build takes place should not be deleted. The path of the build directory is printed as an informational message.

Environment variables

The following environment variables affect the behaviour of nix-store.

TMPDIR=path

Use the directory path to store temporary files. In particular, this includes temporary build directories; these can take up substantial amounts of disk space. The default is /tmp.

Operation --realise

Synopsis

nix-store { --realise | -r } paths...

Description

The operation --install realises in the file system the store expressions stored in paths. If these expressions are derivation expressions, they are first normalised into a closure expression. This may happen in two ways. First, the corresponding closure expression (the successor) may already known (either because the build has already been performed, or because a successor was explicitly registered through the --successor operation). Otherwise, the build action described by the derivation is performed, and a closure expression is computed by scanning the result of the build for references to other paths in the store.

The paths of the closure expression corresponding to each expression in paths is printed on standard output.

Operation --delete

Synopsis

nix-store { --delete | -d } paths...

Description

The operation --delete unconditionally deletes the paths paths from the Nix store. It is an error to attempt to delete paths outside of the store.

Warning

This operation should almost never be called directly, since no attempt is made to verify that no references exist to the paths to be deleted. Therefore, careless deletion can result in an inconsistent system. Deletion of paths in the store is done by the garbage collector (which uses --delete to delete unreferenced paths).

Operation --query

Synopsis

nix-store { --query | -q } { --list | -l | --requisites | -R | --predecessors | --graph } [--normalise] [-n] [--force-realise] [-f] args...

Description

The operation --query displays various bits of information about store expressions or store paths. The queries are described below. At most one query can be specified. The default query is --list.

Common query options

--normalise / -n

For those queries that take a Nix store expression, this option causes those expressions to be normalised first.

--force-realise / -f

For those queries that take a Nix store expression, this option causes those expressions to be realised first. This is just a short-cut for the common idiom

nix-store --realise /nix/store/bla.store
x=`nix-store --query --normalise /nix/store/bla.store`
(do something with the path $x

which using this flag can be written as

x=`nix-store --query --normalise --force-realise /nix/store/bla.store`
(do something with the path $x

Queries

--list / -l

Prints out the output paths of the store expressions indicated by the identifiers args. In the case of a derivation expression, these are the paths that will be produced when the derivation is realised. In the case of a closure expression, these are the paths that were produced the derivation expression of which the closure expression is a successor.

--requisites / -R

Prints out the requisite paths of the store expressions indicated by the identifiers args. The requisite paths of a Nix expression are the paths that need to be present in the system to be able to realise the expression. That is, they form the closure of the expression in the file system (i.e., no path in the set of requisite paths points to anything outside the set of requisite paths).

The notion of requisite paths is very useful when one wants to distribute store expressions. Since they form a closure, they are the only paths one needs to distribute to another system to be able to realise the expression on the other system.

This query is generally used to implement various kinds of deployment. A source deployment is obtained by distributing the requisite paths of a derivation expression. A binary deployment is obtained by distributing the requisite paths of a closure expression. A cache deployment is obtained by distributing the requisite paths of a derivation expression and specifying the option --include-successors. This will include not just the paths of a source and binary deployment, but also all expressions and paths of subterms of the source. This is useful if one wants to realise on the target system a Nix expression that is similar but not quite the same as the one being distributed, since any common subterms will be reused.

This query has a number of options:

--exclude-exprs

Excludes the paths of store expressions. This causes the closure property to be lost, that is, the resulting set of paths is not enough to ensure realisibility.

--include-successors

Also include the requisites of successors (normal forms). Only the requisites of known successors are included, i.e., the normal forms of derivation expressions that have never been normalised will not be included.

Note that not just the successor of a derivation expression will be included, but also the successors of all input expressions of that derivation expression. I.e., all normal forms of subterms involved in the normalisation of the top-level term are included.

--predecessors

For each store expression stored at paths args, prints its predecessors. A derivation expression p is a predecessor of a store expression q iff q is a successor of p.

--graph

Prints a graph of the closure of the store expressions identified by args in the format of the dot tool of AT&T's GraphViz package.

Operation --successor

Synopsis

nix-store {--successor} srcpath sucpath...

Description

The operation --successor registers that the closure expression in sucpath is a successor of the derivation expression in srcpath. This is used to implement binary deployment.

Operation --substitute

Synopsis

nix-store {--substitute} srcpath subpath...

Description

The operation --substitute registers that the store path srcpath can be built by realising the derivation expression in subpath. This is used to implement binary deployment.

Operation --verify

Synopsis

nix-store {--verify}

Description

The operation --verify verifies the internal consistency of the Nix database, and the consistency between the Nix database and the Nix store. Any inconsistencies encountered are automatically repaired. Inconsistencies are generally the result of the Nix store or database being modified by non-Nix tools, or of bugs in Nix itself.

A.3. nix-instantiate

Name

nix-instantiate — instantiate store expressions from Nix expressions

Synopsis

nix-instantiate [--help] [--version] [--verbose...] [-v...] [--build-output] [-B] [--keep-failed] [-K] files...

Description

The command nix-instantiate generates (low-level) store expressions from (high-level) Nix expressions. It loads and evaluates the Nix expressions in each of files. Each top-level expression should evaluate to a derivation, a list of derivations, or a set of derivations. The paths of the resulting store expressions are printed on standard output.

This command is generally used for testing Nix expression before they are used with nix-env.

Options

--help

Prints out a summary of the command syntax and exits.

--version

Prints out the Nix version number on standard output and exits.

--verbose / -v

Increases the level of verbosity of diagnostic messages printed on standard error. For each Nix operation, the information printed on standard output is well-defined; any diagnostic information is printed on standard error, never on standard output.

This option may be specified repeatedly. Currently, the following verbosity levels exist:

0

Errors only”: only print messages explaining why the Nix invocation failed.

1

Informational”: print useful messages about what Nix is doing.

2

Talkative”: print more informational messages.

3

Chatty”: print even more informational messages.

4

Debug”: print debug information:

5

Vomit”: print vast amounts of debug information.

--build-output / -B

Causes the output written by build actions to standard output and standard error to be echoed to standard error, regardless of verbosity level. By default, it is only echoed at a verbosity level of at least 4 (“Debug”), and is suppressed at lower levels. Note that it is always written to a log file in prefix/nix/var/log/nix.

--keep-failed / -K

Specifies that in case of a build failure, the temporary directory (usually in /tmp) in which the build takes place should not be deleted. The path of the build directory is printed as an informational message.

Examples

$ nix-instantiate gcc.nix (instantiate)
/nix/store/468abdcb93aa22bb721142615b97698b-d-gcc-3.3.2.store

$ nix-store -r $(nix-instantiate gcc.nix) (build)

$ nix-store -r $(nix-instantiate gcc.nix) (print output path)
/nix/store/9afa718cddfdfe94b5b9303d0430ceb1-gcc-3.3.2

$ ls -l /nix/store/9afa718cddfdfe94b5b9303d0430ceb1-gcc-3.3.2
dr-xr-xr-x    2 eelco    users         360 2003-12-01 16:12 bin
dr-xr-xr-x    3 eelco    users          72 2003-12-01 16:12 include
...

A.4. nix-collect-garbage

Name

nix-collect-garbage — determine the set of unreachable store paths

Synopsis

nix-collect-garbage [--invert] [--no-successors]

Description

The command nix-collect-garbage determines the paths in the Nix store that are garbage, that is, not reachable from outside of the store. These paths can be safely deleted without affecting the integrity of the system.

Options

--invert

Causes the set of reachable paths to be printed, rather than the unreachable paths. These are the paths that may not be deleted.

--no-successors

Causes nix-collect-garbage not to follow successor relations. By default, if a derivation store expression is reachable, its successor (i.e., a closure store expression) is also considered to be reachable. This option is always safe, but garbage collecting successors may cause undesirable rebuilds later on.

Examples

To delete all unreachable paths, do the following:

$ nix-collect-garbage | xargs nix-store --delete

A.5. nix-push

Name

nix-push — push store paths onto a network cache

Synopsis

nix-push archives-put-url archives-get-url manifest-put-url paths...

Description

The command nix-push builds a set of store expressions (if necessary), and then packages and uploads all store paths in the resulting closures to a server. A network cache thus populated can subsequently be used to speed up software deployment on other machines using the nix-pull command.

nix-push performs the following actions.

  1. The store expressions stored in paths are realised (using nix-store --realise).

  2. All paths in the closure of the store expressions stored in paths are determined (using nix-store --query --requisites --include-successors). It should be noted that since the --include-successors flag is used, if you specify a derivation store expression, you get a combined source/binary distribution. If you only want a binary distribution, you should specify the closure store expression that result from realising these (see below).

  3. All store paths determined in the previous step are packaged and compressed into a bzipped NAR archive (extension .nar.bz2).

  4. A manifest is created that contains information on the store paths, their eventual URLs in the cache, and cryptographic hashes of the contents of the NAR archives.

  5. Each store path is uploaded to the remote directory specified by archives-put-url. HTTP PUT requests are used to do this. However, before a file x is uploaded to archives-put-url/x, nix-push first determines whether this upload is unnecessary by issuing a HTTP HEAD request on archives-get-url/x. This allows a cache to be shared between many partially overlapping nix-push invocations. (We use two URLs because the upload URL typically refers to a CGI script, while the download URL just refers to a file system directory on the server.)

  6. The manifest is uploaded using an HTTP PUT request to manifest-put-url. The corresponding URL to download the manifest can then be used by nix-pull.

Examples

To upload files there typically is some CGI script on the server side. This script should be be protected with a password. The following example uploads the store paths resulting from building the Nix expressions in foo.nix, passing appropriate authentication information:

$ nix-push \
    http://foo@bar:server.domain/cgi-bin/upload.pl/cache \
    http://server.domain/cache \
    http://foo@bar:server.domain/cgi-bin/upload.pl/MANIFEST \
    $(nix-instantiate foo.nix)

This will push both sources and binaries (and any build-time dependencies used in the build, such as compilers).

If we just want to push binaries, not sources and build-time dependencies, we can do:

$ nix-push urls $(nix-instantiate $(nix-store -r foo.nix))

A.6. nix-pull

Name

nix-pull — pull substitutes from a network cache

Synopsis

nix-pull url

Description

The command nix-pull obtains a list of pre-built store paths from the URL url, and for each of these store paths, registers a substitute derivation that downloads and unpacks it into the Nix store. This is used to speed up installations: if you attempt to install something that has already been built and stored into the network cache, Nix can transparently re-use the pre-built store paths.

The file at url must be compatible with the files created by nix-push.

Examples

$ nix-pull http://catamaran.labs.cs.uu.nl/dist/nix/nixpkgs-0.5pre753/MANIFEST

A.7. nix-prefetch-url

Name

nix-prefetch-url — copy a file from a URL into the store and print its MD5 hash

Synopsis

nix-prefetch-url url

Description

The command nix-prefetch-url downloads the file referenced by the URL url, prints its MD5 cryptographic hash code, and copies it into the Nix store. The file name in the store is hash-basename, where basename is everything following the final slash in url.

This command is just a convenience to Nix expression writers. Often a Nix expressions fetch some source distribution from the network using the fetchurl expression contained in nixpkgs. However, fetchurl requires an MD5 hash. If you don't know the hash, you would have to download the file first, and then fetchurl would download it again when you build your Nix expression. Since fetchurl uses the same name for the downloaded file as nix-prefetch-url, the redundant download can be avoided.

Examples

$ nix-prefetch-url ftp://ftp.nluug.nl/pub/gnu/make/make-3.80.tar.bz2
...
file has hash 0bbd1df101bc0294d440471e50feca71
...

Chapter 5. Nix Language Reference

5.1. Grammar

Expressions
[1]Expr::= ExprFunction  
[2]ExprFunction::= '{' Formals '}' ':' ExprFunction
| ExprAssert
 
[3]ExprAssert::= 'assert' Expr ';' ExprAssert
| ExprIf
 
[4]ExprIf::= 'if' Expr 'then' Expr 'else' Expr
| ExprOp
 
[5]ExprOp::= '!' ExprOp
| ExprOp '==' ExprOp
| ExprOp '!=' ExprOp
| ExprOp '&&' ExprOp
| ExprOp '||' ExprOp
| ExprOp '->' ExprOp
| ExprOp '//' ExprOp
| ExprOp '~' ExprOp
| ExprOp '?' Id
| ExprApp
 
[6]ExprApp::= ExprApp '.' ExprSelect
| ExprSelect
 
[7]ExprSelect::= ExprSelect Id
| ExprSimple
 
[8]ExprSimple::= Id | Int | Str | Path | Uri
| 'true' | 'false' | 'null'
| '(' Expr ')'
| '{' Bind* '}'
| 'let' '{' Bind* '}'
| 'rec' '{' Bind* '}'
| '[' ExprSelect* ']'
 
[9]Bind::= Id '=' Expr ';'
| 'inherit' ('(' Expr ')')? Id* ';'
 
[10]Formals::= Formal ',' Formals | Formal  
[11]Formal::= Id
| Id '?' Expr
 
Terminals
[12]Id::=[a-zA-Z\_][a-zA-Z0-9\_\']* 
[13]Int::=[0-9]+ 
[14]Str::=\"[^\n\"]*\" 
[15]Path::=[a-zA-Z0-9\.\_\-\+]*(\/[a-zA-Z0-9\.\_\-\+]+)+ 
[16]Uri::=[a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\']+ 
[17]Whitespace::= [ \t\n]+
| \#[^\n]*
| \/\*(.|\n)*\*\/
 

5.2. Semantics

5.2.1. Built-in functions

The Nix language provides the following built-in function (“primops”):

import e

Evaluates the expression e, which must yield a path value. The Nix expression stored at this path in the file system is then read, parsed, and evaluated. Returns the result of the evaluation of the Nix expression just read.

Example: import ./foo.nix evaluates the expression stored in foo.nix (in the directory containing the expression in which the import occurs).

derivation e

Evaluates the expression e, which must yield an attribute set. [...]

baseNameOf e

Evaluates the expression e, which must yield a string value, and returns a string representing its base name. This is the substring following the last path separator (/).

Example: baseNameOf "/foo/bar" returns "bar", and baseNameOf "/foo/bar/" returns "".

toString e

Evaluates the expression e and coerces it into a string, if possible. Only strings, paths, and URIs can be so coerced.

Example: toString http://www.cs.uu.nl/ returns "http://www.cs.uu.nl/".

Appendix B. Troubleshooting

(Nothing.)

Appendix C. Bugs / To-Do

  • The man-pages generated from the DocBook documentation are ugly.

  • Generations properly form a tree. E.g., if after switching to generation 39, we perform an installation action, a generation 43 is created which is a descendant of 39, not 42. So a rollback from 43 ought to go back to 39. This is not currently implemented; generations form a linear sequence.

  • Unify the concepts of successors and substitutes into a general notion of equivalent expressions. Expressions are equivalent if they have the same target paths with the same identifiers. However, even though they are functionally equivalent, they may differ stronly with respect to their performance characteristics. For example, realising a closure expression is more efficient that realising the derivation expression from which it was produced. On the other hand, distributing sources may be more efficient (storage- or bandwidth-wise) than distributing binaries. So we need to be able to attach weigths or priorities or performance annotations to expressions; Nix can then choose the most efficient expression dependent on the context.

  • Build management. In principle it is already possible to do build management using Nix (by writing builders that perform appropriate build steps), but the Nix expression language is not yet powerful enough to make this pleasant (?). The language should be extended with features from the Maak build manager. Another interesting idea is to write a make implementation that uses Nix as a back-end to support legacy build files.

  • The current garbage collector is a hack. It should be integrated into nix-store. It should delete derivations in an order determined by topologically sorting derivations under the points-to relation. This ensures that no store paths ever exist that point to non-existant store paths.

  • There are race conditions between the garbage collector and other Nix tools. For instance, when we run nix-env to build and install a derivation and run the garbage collector at the same time, the garbage collector may kick in exactly between the build and installation steps, i.e., before the newly built derivation has become reachable from a root of the garbage collector.

    One solution would be for these programs to properly register temporary roots for the collector. Another would be to use stop-the-world garbage collection: if any tool is running, the garbage collector blocks, and vice versa. These solutions do not solve the situation where multiple tools are involved, e.g.,

    $ nix-store -r $(nix-instantiate foo.nix)

    since even if nix-instantiate where to register a temporary root, it would be released by the time nix-store is started. A solution would be to write the intermediate value to a file that is used as a root to the collector, e.g.,

    $ nix-instantiate foo.nix > /nix/var/nix/roots/bla
    $ nix-store -r $(cat /nix/var/nix/roots/bla)

  • For security, nix-push manifests should be digitally signed, and nix-pull should verify the signatures. The actual NAR archives in the cache do not need to be signed, since the manifest contains cryptographic hashes of these files (and fetchurl.nix checks them).