455 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			455 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
<chapter id='chap-package-management'><title>Package Management</title>
 | 
						|
 | 
						|
<para>This chapter discusses how to do package management with Nix,
 | 
						|
i.e., how to obtain, install, upgrade, and erase components.  This is
 | 
						|
the <quote>user's</quote> perspective of the Nix system — people
 | 
						|
who want to <emphasis>create</emphasis> components should consult
 | 
						|
<xref linkend='chap-writing-nix-expressions' />.</para>
 | 
						|
 | 
						|
 | 
						|
<sect1><title>Basic package management</title>
 | 
						|
 | 
						|
<para>The main command for package management is
 | 
						|
<command>nix-env</command>.  You can use it to install, upgrade, and
 | 
						|
erase components, and to query what components are installed or are
 | 
						|
available for installation.</para>
 | 
						|
 | 
						|
<para>In Nix, different users can have different <quote>views</quote>
 | 
						|
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 <quote>active</quote> just means that it appears in a directory
 | 
						|
in the user's <envar>PATH</envar>.  Such a view on the set of
 | 
						|
installed applications is called a <emphasis>user
 | 
						|
environment</emphasis>, which is just a directory tree consisting of
 | 
						|
symlinks to the files of the active applications.  </para>
 | 
						|
 | 
						|
<para>Components are installed from a set of <emphasis>Nix
 | 
						|
expressions</emphasis> 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 it, or completely new ones.)  You can download the
 | 
						|
latest version from <ulink
 | 
						|
url='http://catamaran.labs.cs.uu.nl/dist/nix' />.  You probably want
 | 
						|
the latest unstable release; currently the stable releases tend to lag
 | 
						|
behind quite a bit.</para>
 | 
						|
 | 
						|
<para>Assuming that you have downloaded and unpacked a release of Nix
 | 
						|
Packages, you can view the set of available components in the release:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -qaf nixpkgs-<replaceable>version</replaceable>
 | 
						|
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
 | 
						|
...</screen>
 | 
						|
 | 
						|
where <literal>nixpkgs-<replaceable>version</replaceable></literal> is
 | 
						|
where you've unpacked the release.</para>
 | 
						|
 | 
						|
<para>It is also possible to see the <emphasis>status</emphasis> of
 | 
						|
available components, i.e., whether they are installed into the user
 | 
						|
environment and/or present in the system:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -qasf nixpkgs-<replaceable>version</replaceable>
 | 
						|
...
 | 
						|
-PS bash-3.0
 | 
						|
--S binutils-2.15
 | 
						|
IPS bison-1.875d
 | 
						|
...</screen>
 | 
						|
 | 
						|
The first character (<literal>I</literal>) indicates whether the
 | 
						|
component is installed in your current user environment.  The second
 | 
						|
(<literal>P</literal>) 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 (<literal>S</literal>) indicates
 | 
						|
whether there is a so-called <emphasis>substitute</emphasis> 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.</para>
 | 
						|
 | 
						|
<para>So now that we have a set of Nix expressions we can build the
 | 
						|
components contained in them.  This is done using <literal>nix-env
 | 
						|
-i</literal>.  For instance,
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -f nixpkgs-<replaceable>version</replaceable> -i subversion</screen>
 | 
						|
 | 
						|
will install the component called <literal>subversion</literal> (which
 | 
						|
is, of course, the <ulink
 | 
						|
url='http://subversion.tigris.org/'>Subversion version management
 | 
						|
system</ulink>).</para>
 | 
						|
 | 
						|
<para>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 components are
 | 
						|
available somewhere.  This is done using the
 | 
						|
<command>nix-pull</command> command, which must be supplied with a URL
 | 
						|
containing a <emphasis>manifest</emphasis> 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
 | 
						|
<ulink
 | 
						|
url='http://catamaran.labs.cs.uu.nl/dist/nix/nixpkgs-0.6pre1554/' />,
 | 
						|
then you should do:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-pull http://catamaran.labs.cs.uu.nl/dist/nix/nixpkgs-0.6pre1554/MANIFEST</screen>
 | 
						|
 | 
						|
If you then issue the installation command, it should start
 | 
						|
downloading binaries from <systemitem
 | 
						|
class='fqdomainname'>catamaran.labs.cs.uu.nl</systemitem>, 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.</para>
 | 
						|
 | 
						|
<para>Naturally, packages can also be uninstalled:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -e subversion</screen>
 | 
						|
 | 
						|
</para>
 | 
						|
 | 
						|
<para>Upgrading to a new version is just as easy.  If you have a new
 | 
						|
release of Nix Packages, you can do:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -f nixpkgs-<replaceable>version</replaceable> -u subversion</screen>
 | 
						|
 | 
						|
This will <emphasis>only</emphasis> upgrade Subversion if there is a
 | 
						|
<quote>newer</quote> 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 <parameter>-i</parameter> instead of
 | 
						|
<parameter>-u</parameter>; <parameter>-i</parameter> will remove
 | 
						|
whatever version is already installed.</para>
 | 
						|
 | 
						|
<para>You can also upgrade all components for which there are newer
 | 
						|
versions:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -f nixpkgs-<replaceable>version</replaceable> -u '*'</screen>
 | 
						|
 | 
						|
</para>
 | 
						|
 | 
						|
<para>Sometimes it's useful to be able to ask what
 | 
						|
<command>nix-env</command> would do, without actually doing it.  For
 | 
						|
instance, to find out what packages would be upgraded by
 | 
						|
<literal>nix-env -u '*'</literal>, you can do
 | 
						|
 | 
						|
<screen>
 | 
						|
$ 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'</screen>
 | 
						|
 | 
						|
</para>
 | 
						|
 | 
						|
<para>If you grow bored of specifying the Nix expressions using
 | 
						|
<parameter>-f</parameter> all the time, you can set a default
 | 
						|
location:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -I nixpkgs-<replaceable>version</replaceable></screen>
 | 
						|
 | 
						|
After this you can just say, for instance, <literal>nix-env -u
 | 
						|
'*'</literal>.<footnote><para>Setting a default using
 | 
						|
<parameter>-I</parameter> currently clashes with using Nix channels,
 | 
						|
since <literal>nix-channel --update</literal> calls <literal>nix-env
 | 
						|
-I</literal> to set the default to the Nix expressions it downloaded
 | 
						|
from the channel, replacing whatever default you had
 | 
						|
set.</para></footnote></para>
 | 
						|
 | 
						|
</sect1>
 | 
						|
 | 
						|
 | 
						|
<sect1><title>Profiles</title>
 | 
						|
 | 
						|
<para>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
 | 
						|
<emphasis>Nix store</emphasis> (typically,
 | 
						|
<filename>/nix/store</filename>).  For instance, a particular version
 | 
						|
of the Subversion component might be stored in a directory
 | 
						|
<filename>/nix/store/eeeeaf42e56b...-subversion-0.32.1/</filename>,
 | 
						|
while another version might be stored in
 | 
						|
<filename>/nix/store/58823d558a6a...-subversion-0.34/</filename>.  The
 | 
						|
long hexadecimal numbers prefixed to the directory names are
 | 
						|
cryptographic hashes<footnote><para>128 bit MD5 hashes, to be
 | 
						|
precise.</para></footnote> of <emphasis>all</emphasis> 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.  <xref linkend='fig-user-environments'
 | 
						|
/><footnote><para>TODO: the figure isn't entirely up to date.  It
 | 
						|
should show multiple profiles and
 | 
						|
<filename>~/.nix-profile</filename>.</para></footnote> shows a part of
 | 
						|
a typical Nix store.</para>
 | 
						|
 | 
						|
<figure id='fig-user-environments'><title>User environments</title>
 | 
						|
  <mediaobject>
 | 
						|
    <imageobject>
 | 
						|
      <imagedata fileref='figures/user-environments.png' format='PNG' />
 | 
						|
    </imageobject>
 | 
						|
  </mediaobject>
 | 
						|
</figure>
 | 
						|
 | 
						|
<para>Of course, you wouldn't want to type
 | 
						|
 | 
						|
<screen>
 | 
						|
$ /nix/store/eeeeaf42e56b...-subversion-0.32.1/bin/svn</screen>
 | 
						|
 | 
						|
every time you want to run Subversion.  Of course we could set up the
 | 
						|
<envar>PATH</envar> environment variable to include the
 | 
						|
<filename>bin</filename> directory of every component we want to use,
 | 
						|
but this is not very convenient since changing <envar>PATH</envar>
 | 
						|
doesn't take effect for already existing processes.  The solution Nix
 | 
						|
uses is to create directory trees of symlinks to
 | 
						|
<emphasis>activated</emphasis> components.  These are called
 | 
						|
<emphasis>user environments</emphasis> and they are components
 | 
						|
themselves (though automatically generated by
 | 
						|
<command>nix-env</command>), so they too reside in the Nix store.  For
 | 
						|
instance, in <xref linkend='fig-user-environments' /> the user
 | 
						|
environment <filename>/nix/store/068150f63831...-user-env</filename>
 | 
						|
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
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -i subversion</screen>
 | 
						|
 | 
						|
on a set of Nix expressions that contained Subversion 0.32.1.</para>
 | 
						|
 | 
						|
<para>This doesn't in itself solve the problem, of course; you
 | 
						|
wouldn't want to type
 | 
						|
<filename>/nix/store/068150f63831...-user-env/bin/svn</filename>
 | 
						|
either.  Therefore there are symlinks outside of the store that point
 | 
						|
to the user environments in the store; for instance, the symlinks
 | 
						|
<filename>42</filename> and <filename>43</filename> in the example.
 | 
						|
These are called <emphasis>generations</emphasis> since every time you
 | 
						|
perform a <command>nix-env</command> operation, a new user environment
 | 
						|
is generated based on the current one.  For instance, generation 43
 | 
						|
was created from generation 42 when we did
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -i subversion mozilla</screen>
 | 
						|
 | 
						|
on a set of Nix expressions that contained Mozilla and a new version
 | 
						|
of Subversion.</para>
 | 
						|
 | 
						|
<para>Generations are grouped together into
 | 
						|
<emphasis>profiles</emphasis> so that different users don't interfere
 | 
						|
with each other if they don't want to.  For example:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ 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</screen>
 | 
						|
 | 
						|
This shows a profile called <filename>default</filename>.  The file
 | 
						|
<filename>default</filename> itself is actually a symlink that points
 | 
						|
to the current generation.  When we do a <command>nix-env</command>
 | 
						|
operation, a new user environment and generation link are created
 | 
						|
based on the current one, and finally the <filename>default</filename>
 | 
						|
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.)</para>
 | 
						|
 | 
						|
<para>If you find that you want to undo a <command>nix-env</command>
 | 
						|
operation, you can just do
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env --rollback</screen>
 | 
						|
 | 
						|
which will just make the current generation link point at the previous
 | 
						|
link.  E.g., <filename>default</filename> would be made to point at
 | 
						|
<filename>default-42-link</filename>.  You can also switch to a
 | 
						|
specific generation:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env --switch-generation 43</screen>
 | 
						|
 | 
						|
which in this example would roll forward to generation 43 again.  You
 | 
						|
can also see all available generations:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env --list-generations</screen></para>
 | 
						|
 | 
						|
<para>Actually, there is another level of indirection not shown in the
 | 
						|
figure above.  You generally wouldn't have
 | 
						|
<filename>/nix/var/nix/profiles/<replaceable>some-profile</replaceable>/bin</filename>
 | 
						|
in your <envar>PATH</envar>.  Rather, there is a symlink
 | 
						|
<filename>~/.nix-profile</filename> that points to your current
 | 
						|
profile.  This means that you should put
 | 
						|
<filename>~/.nix-profile/bin</filename> in your <envar>PATH</envar>
 | 
						|
(and indeed, that's what the initialisation script
 | 
						|
<filename>/nix/etc/profile.d/nix.sh</filename> does).  This makes it
 | 
						|
easier to switch to a different profile.  You can do that using the
 | 
						|
command <command>nix-env --switch-profile</command>:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env --switch-profile /nix/var/nix/profiles/my-profile
 | 
						|
 | 
						|
$ nix-env --switch-profile /nix/var/nix/profiles/default</screen>
 | 
						|
 | 
						|
These commands switch to the <filename>my-profile</filename> 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 <filename>profiles</filename>
 | 
						|
directory, since otherwise it might not be used as a root of the
 | 
						|
garbage collector (see section <xref linkend='sec-garbage-collection'
 | 
						|
/>).</para>
 | 
						|
 | 
						|
<para>All <command>nix-env</command> operations work on the profile
 | 
						|
pointed to by <command>~/.nix-profile</command>, but you can override
 | 
						|
this using the <option>--profile</option> option (abbreviation
 | 
						|
<option>-p</option>):
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -p /nix/var/nix/profiles/other-profile -i subversion</screen>
 | 
						|
 | 
						|
This will <emphasis>not</emphasis> change the
 | 
						|
<command>~/.nix-profile</command> symlink.</para>
 | 
						|
 | 
						|
</sect1>
 | 
						|
 | 
						|
 | 
						|
<sect1 id='sec-garbage-collection'><title>Garbage collection</title>
 | 
						|
 | 
						|
<para><command>nix-env</command> operations such as upgrades
 | 
						|
(<option>-u</option>) and uninstall (<option>-e</option>) never
 | 
						|
actually delete components from the system.  All they do (as shown
 | 
						|
above) is to create a new user environment that no longer contains
 | 
						|
symlinks to the <quote>deleted</quote> components.</para>
 | 
						|
 | 
						|
<para>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.</para>
 | 
						|
 | 
						|
<para>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.</para>
 | 
						|
 | 
						|
<para>To delete all old (non-current) generations of your current
 | 
						|
profile:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env --delete-generations old</screen>
 | 
						|
 | 
						|
Instead of <literal>old</literal> you can also specify a list of
 | 
						|
generations, e.g.,
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env --delete-generations 10 11 14</screen>
 | 
						|
 | 
						|
</para>
 | 
						|
 | 
						|
<para>After removing appropriate old generations you can run the
 | 
						|
garbage collector as follows:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-collect-garbage</screen>
 | 
						|
 | 
						|
You can alo first view what files would be deleted:
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-collect-garbage --print-dead</screen>
 | 
						|
 | 
						|
Likewise, the option <option>--print-live</option> will show the paths
 | 
						|
that <emphasis>won't</emphasis> be deleted.</para>
 | 
						|
 | 
						|
<sect2><title>Garbage collector roots</title>
 | 
						|
 | 
						|
<para>TODO</para>
 | 
						|
 | 
						|
<para>The garbage collector uses as roots all store expressions
 | 
						|
mentioned in all files with extension <filename>.gcroot</filename> in
 | 
						|
the directory
 | 
						|
<filename><replaceable>prefix</replaceable>/var/nix/gcroots/</filename>,
 | 
						|
or in any file or directory symlinked to from that directory.  E.g.,
 | 
						|
by default,
 | 
						|
<filename><replaceable>prefix</replaceable>/var/nix/gcroots/</filename>
 | 
						|
contains a symlink to
 | 
						|
<filename><replaceable>prefix</replaceable>/var/nix/profiles/</filename>,
 | 
						|
so all generations of all profiles are also roots of the collector.</para>
 | 
						|
 | 
						|
</sect2>
 | 
						|
 | 
						|
</sect1>
 | 
						|
 | 
						|
 | 
						|
<sect1><title>Channels</title>
 | 
						|
 | 
						|
<para>If 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 <command>nix-pull</command> to register
 | 
						|
pre-built binaries (if available), and upgrade using
 | 
						|
<command>nix-env</command>.  Fortunately, there's a better way:
 | 
						|
<emphasis>Nix channels</emphasis>.</para>
 | 
						|
 | 
						|
<para>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
 | 
						|
<command>nix-channel</command> you can automatically stay up to date
 | 
						|
with whatever is available at that URL.</para>
 | 
						|
 | 
						|
<para>You can <quote>subscribe</quote> to a channel using
 | 
						|
<command>nix-channel --add</command>, e.g.,
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-channel --add http://catamaran.labs.cs.uu.nl/dist/nix/channels/nixpkgs-unstable</screen>
 | 
						|
 | 
						|
subscribes you to a channel that always contains that latest version
 | 
						|
of the Nix Packages collection.  (Instead of
 | 
						|
<literal>nixpkgs-unstable</literal> you could also subscribe to
 | 
						|
<literal>nixpkgs-stable</literal>, 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
 | 
						|
<filename>~/.nix-channels</filename>.  Right now there is no command
 | 
						|
to <quote>unsubscribe</quote>; you should just edit that file manually
 | 
						|
and delete the offending URL.</para>
 | 
						|
 | 
						|
<para>To obtain the latest Nix expressions available in a channel, do
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-channel --update</screen>
 | 
						|
 | 
						|
This downloads the Nix expressions in every channel (downloaded from
 | 
						|
<literal><replaceable>url</replaceable>/nixexprs.tar.bz2</literal>)
 | 
						|
and registers any available pre-built binaries in every channel
 | 
						|
(by <command>nix-pull</command>ing
 | 
						|
<literal><replaceable>url</replaceable>/MANIFEST</literal>).  It also
 | 
						|
makes the union of each channel's Nix expressions the default for
 | 
						|
<command>nix-env</command> operations.  Consequently, you can then say
 | 
						|
 | 
						|
<screen>
 | 
						|
$ nix-env -u '*'</screen>
 | 
						|
 | 
						|
to upgrade all components in your profile to the latest versions
 | 
						|
available in the subscribed channels.</para>
 | 
						|
 | 
						|
</sect1>
 | 
						|
 | 
						|
 | 
						|
</chapter>
 |