Package ManagementThis chapter discusses how to do package management with Nix,
i.e., how to obtain, install, upgrade, and erase packages. This is
the “user’s” perspective of the Nix system — people
who want to create packages should consult
.Basic package managementThe main command for package management is nix-env. You can use
it to install, upgrade, and erase packages, and to query what
packages 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 packages,
including, if necessary, their dependencies. There is a collection of
Nix expressions called the Nix Package collection that contains
packages 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
expressions based on it, or completely new ones.) You can download
the latest version from .Assuming that you have downloaded and unpacked a release of Nix
Packages, you can view the set of available packages 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. The flag
specifies a query operation; means that you want
to show the “available” (i.e., installable) packages, as opposed to
the installed packages; and
nixpkgs-version
specifies the source of the packages. The argument
'*' shows all installable packages. (The quotes are
necessary to prevent shell expansion.) You can also select specific
packages by name:
$ nix-env -qaf nixpkgs-version gcc
gcc-3.4.6
gcc-4.0.3
gcc-4.1.1It 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 nixpkgs-version '*'
...
-PS bash-3.0
--S binutils-2.15
IPS bison-1.875d
...
The first character (I) indicates whether the
package 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 a
very quick operation). The last one (S) indicates
whether there is a so-called substitute for the
package, which is Nix’s mechanism for doing binary deployment. It
just means that Nix knows that it can fetch a pre-built package 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
packages contained in them. This is done using nix-env
-i. For instance,
$ nix-env -f nixpkgs-version -i subversion
will install the package 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 do a Ctrl-C on that install operation!): you just need
to tell Nix that pre-built binaries of all those packages 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://nixos.org/releases/nixpkgs/nixpkgs-0.12pre11712-4lrp7j8x/MANIFEST
If you then issue the installation command, it should start
downloading binaries from nixos.org, 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 DSL line it’s on the order of a few minutes.Naturally, packages can also be uninstalled:
$ nix-env -e subversionUpgrading 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 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 packages 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.ProfilesProfiles and user environments are Nix’s mechanism for
implementing the ability to allow different 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, packages are stored in unique locations in the
Nix store (typically,
/nix/store). For instance, a particular version
of the Subversion package might be stored in a directory
/nix/store/dpmvp969yhdqs7lm2r1a3gng7pyq6vy4-subversion-1.1.3/,
while another version might be stored in
/nix/store/5mq2jcn36ldlmh93yj1n8s9c95pj7c5s-subversion-1.1.2.
The long strings prefixed to the directory names are cryptographic
hashes160-bit truncations of SHA-256 hashes encoded in
a base-32 notation, to be precise. of
all inputs involved in building the package —
sources, dependencies, compiler flags, and so on. So if two
packages differ in any way, they end up in different locations in
the file system, so they don’t interfere with each other. shows a part of a typical Nix
store.Of course, you wouldn’t want to type
$ /nix/store/dpmvp969yhdq...-subversion-1.1.3/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 package 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 packages. These are called
user environments and they are packages
themselves (though automatically generated by
nix-env), so they too reside in the Nix store. For
instance, in the user
environment /nix/store/5mq2jcn36ldl...-user-env
contains a symlink to just Subversion 1.1.2 (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 1.1.2.This doesn’t in itself solve the problem, of course; you
wouldn’t want to type
/nix/store/0c1p5z4kda11...-user-env/bin/svn
either. That’s why there are symlinks outside of the store that point
to the user environments in the store; for instance, the symlinks
default-42-link and
default-43-link 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/0c1p5z4kda11...-user-env
lrwxrwxrwx 1 eelco ... default-43-link -> /nix/store/3aw2pdyx2jfc...-user-env
lrwxrwxrwx 1 eelco ... default -> default-43-link
This shows a profile called default. The file
default itself is actually a symlink that points
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 packages doesn’t interfere in
any way with old packages, 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-generationsActually, 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 points 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. You can do that using the
command nix-env --switch-profile:
$ 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 than the profiles
directory, since otherwise it might not be used as a root of the
garbage collector (see ).All nix-env operations work on the profile
pointed to by ~/.nix-profile, but you can override
this using the option (abbreviation
):
$ nix-env -p /nix/var/nix/profiles/other-profile -i subversion
This will not change the
~/.nix-profile symlink.Garbage collectionnix-env operations such as upgrades
() and uninstall () never
actually delete packages from the system. All they do (as shown
above) is to create a new user environment that no longer contains
symlinks to the “deleted” packages.Of course, since disk space is not infinite, unused packages
should be removed at some point. You can do this by running the Nix
garbage collector. It will remove from the Nix store any package
not used (directly or indirectly) by any generation of any
profile.Note however that as long as old generations reference a
package, 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 14After removing appropriate old generations you can run the
garbage collector as follows:
$ nix-store --gc
If you are feeling uncertain, you can also first view what files would
be deleted:
$ nix-store --gc --print-dead
Likewise, the option will show the paths
that won’t be deleted.There is also a convenient little utility
nix-collect-garbage, which when invoked with the
() switch deletes all
old generations of all profiles in
/nix/var/nix/profiles. So
$ nix-collect-garbage -d
is a quick and easy way to clean up your system.Garbage collector rootsThe roots of the garbage collector are all store paths to which
there are symlinks in the directory
prefix/nix/var/nix/gcroots.
For instance, the following command makes the path
/nix/store/d718ef...-foo a root of the collector:
$ ln -s /nix/store/d718ef...-foo /nix/var/nix/gcroots/bar
That is, after this command, the garbage collector will not remove
/nix/store/d718ef...-foo or any of its
dependencies.Subdirectories of
prefix/nix/var/nix/gcroots
are also searched for symlinks. Symlinks to non-store paths are
followed and searched for roots, but symlinks to non-store paths
inside the paths reached in that way are not
followed to prevent infinite recursion.ChannelsIf you want to stay up to date with a set of packages, it’s not
very convenient to manually download the latest set of Nix expressions
for those packages, use nix-pull to register
pre-built binaries (if available), and upgrade using
nix-env. Fortunately, there’s a better way:
Nix channels.A Nix channel is just a URL that points to a place that contains
a set of Nix expressions and a manifest. Using the command nix-channel you
can automatically stay up to date with whatever is available at that
URL.You can “subscribe” to a channel using
nix-channel --add, e.g.,
$ nix-channel --add http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable
subscribes you to a channel that always contains that latest version
of the Nix Packages collection. (Instead of
nixpkgs-unstable you could also subscribe to
nixpkgs-stable, which should have a higher level of
stability, but right now is just outdated.) Subscribing really just
means that the URL is added to the file
~/.nix-channels. Right now there is no command
to “unsubscribe”; you should just edit that file manually
and delete the offending URL.To obtain the latest Nix expressions available in a channel, do
$ nix-channel --update
This downloads the Nix expressions in every channel (downloaded from
url/nixexprs.tar.bz2)
and registers any available pre-built binaries in every channel
(by nix-pulling
url/MANIFEST). It also
makes the union of each channel’s Nix expressions the default for
nix-env operations. Consequently, you can then say
$ nix-env -u '*'
to upgrade all packages in your profile to the latest versions
available in the subscribed channels.One-click installsOften, when you want to install a specific package (e.g., from
the Nix
Packages collection), subscribing to a channel is a bit
cumbersome. And channels don’t help you at all if you want to install
an older version of a package than the one provided by the current
contents of the channel, or a package that has been removed from the
channel. That’s when one-click installs come in
handy: you can just go to the web page that contains the package,
click on it, and it will be installed with all the necessary
dependencies.For instance, you can go to and click on any link for the individual packages for your
platform. The first time you do this, your browser will ask what to
do with application/nix-package files. You should
open them with /nix/bin/nix-install-package.
This will open a window that asks you to confirm that you want to
install the package. When you answer Y, the
package and all its dependencies will be installed. This is a binary
deployment mechanism — you get packages pre-compiled for the selected
platform type.You can also install application/nix-package
files from the command line directly. See for details.Sharing packages between machinesSometimes you want to copy a package from one machine to
another. Or, you want to install some packages and you know that
another machine already has some or all of those packages or their
dependencies. In that case there are mechanisms to quickly copy
packages between machines.The command nix-copy-closure copies a Nix
store path along with all its dependencies to or from another machine
via the SSH protocol. It doesn’t copy store paths that are already
present on the target machine. For example, the following command
copies Firefox with all its dependencies:
$ nix-copy-closure --to alice@itchy.example.org $(type -p firefox)
See for details.With nix-store
--export and nix-store --import you can
write the closure of a store path (that is, the path and all its
dependencies) to a file, and then unpack that file into another Nix
store. For example,
$ nix-store --export $(type -p firefox) > firefox.closure
writes the closure of Firefox to a file. You can then copy this file
to another machine and install the closure:
$ nix-store --import < firefox.closure
Any store paths in the closure that are already present in the target
store are ignored. It is also possible to pipe the export into
another command, e.g. to copy and install a closure directly to/on
another machine:
$ nix-store --export $(type -p firefox) | bzip2 | \
ssh alice@itchy.example.org "bunzip2 | nix-store --import"
But note that nix-copy-closure is generally more
efficient in this example because it only copies paths that are not
already present in the target Nix store.Finally, if you can mount the Nix store of a remote machine in
your local filesystem, Nix can copy paths from the remote Nix store to
the local Nix store on demand. For instance,
suppose that you mount a remote machine containing a Nix store via
sshfs:
$ sshfs alice@itchy.example.org:/ /mnt
You should then set the NIX_OTHER_STORES environment
variable to tell Nix about this remote Nix store:
$ export NIX_OTHER_STORES=/mnt/nix
Then if you do any Nix operation, e.g.
$ nix-env -i firefox
and Nix has to build a path that it sees is already present in
/mnt/nix, then it will just copy from there
instead of building it from source.