lix/doc/manual/package-management.xml
2005-04-10 20:54:21 +00:00

462 lines
18 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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 “users” 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 <link
linkend="sec-nix-env"><command>nix-env</command></link>. 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 “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 users <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
expressions based on it, or completely new ones.) You can download
the latest version from <ulink
url='http://catamaran.labs.cs.uu.nl/dist/nix' />.</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 youve 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 Nixs 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 youre 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 its 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
“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 youd 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 its 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 id="sec-profiles"><title>Profiles</title>
<para>Profiles and user environments are Nixs 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, its 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/dpmvp969yhdqs7lm2r1a3gng7pyq6vy4-subversion-1.1.3/</filename>,
while another version might be stored in
<filename>/nix/store/5mq2jcn36ldlmh93yj1n8s9c95pj7c5s-subversion-1.1.2</filename>.
The long strings prefixed to the directory names are cryptographic
hashes<footnote><para>160-bit truncations of SHA-256 hashes encoded in
a base-32 notation, 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 dont interfere with each other. <xref
linkend='fig-user-environments' /> 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 wouldnt want to type
<screen>
$ /nix/store/dpmvp969yhdq...-subversion-1.1.3/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>
doesnt 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/5mq2jcn36ldl...-user-env</filename>
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
<screen>
$ nix-env -i subversion</screen>
on a set of Nix expressions that contained Subversion 1.1.2.</para>
<para>This doesnt in itself solve the problem, of course; you
wouldnt want to type
<filename>/nix/store/0c1p5z4kda11...-user-env/bin/svn</filename>
either. Thats why there are symlinks outside of the store that point
to the user environments in the store; for instance, the symlinks
<filename>default-42-link</filename> and
<filename>default-43-link</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 dont interfere
with each other if they dont want to. For example:
<screen>
$ 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</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 doesnt 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 wouldnt 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, thats 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 doesnt 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 “deleted” 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 wouldnt 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-store --gc</screen>
If you are feeling uncertain, you can also first view what files would
be deleted:
<screen>
$ nix-store --gc --print-dead</screen>
Likewise, the option <option>--print-live</option> will show the paths
that <emphasis>wont</emphasis> be deleted.</para>
<sect2 id="ssec-gc-roots"><title>Garbage collector roots</title>
<para>The roots of the garbage collector are all store paths to which
there are symlinks in the directory
<filename><replaceable>prefix</replaceable>/nix/var/nix/gcroots</filename>.
For instance, the following command makes the path
<filename>/nix/store/d718ef...-foo</filename> a root of the collector:
<screen>
$ ln -s /nix/store/d718ef...-foo /nix/var/nix/gcroots/bar</screen>
That is, after this command, the garbage collector will not remove
<filename>/nix/store/d718ef...-foo</filename> or any of its
dependencies.</para>
<para>Subdirectories of
<filename><replaceable>prefix</replaceable>/nix/var/nix/gcroots</filename>
are also searched for symlinks. Symlinks to non-store paths are
followed and searched for roots, but symlinks to non-store paths
<emphasis>inside</emphasis> the paths reached in that way are not
followed to prevent infinite recursion.</para>
</sect2>
</sect1>
<sect1 id="sec-channels"><title>Channels</title>
<para>If you want to stay up to date with a set of packages, its 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, theres 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 <link
linkend="sec-nix-channel"><command>nix-channel</command></link> you
can automatically stay up to date with whatever is available at that
URL.</para>
<para>You can “subscribe” 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 “unsubscribe”; 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 channels 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>