diff options
Diffstat (limited to 'doc/manual/package-management.xml')
-rw-r--r-- | doc/manual/package-management.xml | 591 |
1 files changed, 591 insertions, 0 deletions
diff --git a/doc/manual/package-management.xml b/doc/manual/package-management.xml new file mode 100644 index 000000000000..e1d24b14772c --- /dev/null +++ b/doc/manual/package-management.xml @@ -0,0 +1,591 @@ +<chapter xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xml: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 packages. This is +the “user’s” perspective of the Nix system — people +who want to <emphasis>create</emphasis> packages should consult +<xref linkend='chap-writing-nix-expressions' />.</para> + + +<section><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 packages, and to query what +packages 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 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 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 <link +xlink:href='http://nixos.org/nixpkgs/download.html' />.</para> + +<para>Assuming that you have downloaded and unpacked a release of Nix +Packages, you can view the set of available packages 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. The flag <option>-q</option> +specifies a query operation; <option>-a</option> means that you want +to show the “available” (i.e., installable) packages, as opposed to +the installed packages; and <option>-f</option> +<filename>nixpkgs-<replaceable>version</replaceable></filename> +specifies the source of the packages. The argument +<literal>'*'</literal> shows all installable packages. (The quotes are +necessary to prevent shell expansion.) You can also select specific +packages by name: + +<screen> +$ nix-env -qaf nixpkgs-<replaceable>version</replaceable> gcc +gcc-3.4.6 +gcc-4.0.3 +gcc-4.1.1</screen> + +</para> + +<para>It is also possible to see the <emphasis>status</emphasis> of +available packages, 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 +package 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 +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.</para> + +<para>So now that we have a set of Nix expressions we can build the +packages 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 package called <literal>subversion</literal> (which +is, of course, the <link +xlink:href='http://subversion.tigris.org/'>Subversion version +management system</link>).</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 packages 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 <link +xlink:href='http://nixos.org/releases/nixpkgs/nixpkgs-0.12pre11712-4lrp7j8x' +/>, then you should do: + +<screen> +$ nix-pull http://nixos.org/releases/nixpkgs/nixpkgs-0.12pre11712-4lrp7j8x/MANIFEST</screen> + +If you then issue the installation command, it should start +downloading binaries from <systemitem +class='fqdomainname'>nixos.org</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 a 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 +“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 <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 packages 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> + +</section> + + +<section xml:id="sec-profiles"><title>Profiles</title> + +<para>Profiles 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 +<emphasis>Nix store</emphasis> (typically, +<filename>/nix/store</filename>). For instance, a particular version +of the Subversion package 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 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. <xref +linkend='fig-user-environments' /> shows a part of a typical Nix +store.</para> + +<figure xml: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/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 package 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> packages. These are called +<emphasis>user environments</emphasis> and they are packages +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/0c1p5z4kda11...-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 doesn’t in itself solve the problem, of course; you +wouldn’t want to type +<filename>/nix/store/0c1p5z4kda11...-user-env/bin/svn</filename> +either. That’s 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 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/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 packages doesn’t interfere in +any way with old packages, 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 <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> + +</section> + + +<section xml: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 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.</para> + +<para>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.</para> + +<para>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.</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>won’t</emphasis> be deleted.</para> + +<para>There is also a convenient little utility +<command>nix-collect-garbage</command>, which when invoked with the +<option>-d</option> (<option>--delete-old</option>) switch deletes all +old generations of all profiles in +<filename>/nix/var/nix/profiles</filename>. So + +<screen> +$ nix-collect-garbage -d</screen> + +is a quick and easy way to clean up your system.</para> + + + + +<section xml: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> + +</section> + +</section> + + +<section xml:id="sec-channels"><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 <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://nixos.org/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 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 packages in your profile to the latest versions +available in the subscribed channels.</para> + +</section> + + +<section xml:id="sec-one-click"><title>One-click installs</title> + +<para>Often, when you want to install a specific package (e.g., from +the <link +xlink:href="http://nixos.org/nixpkgs/">Nix +Packages collection</link>), 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 <emphasis>one-click installs</emphasis> 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.</para> + +<para>For instance, you can go to <link +xlink:href="http://hydra.nixos.org/jobset/nixpkgs/trunk/channel/latest" +/> 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 <literal>application/nix-package</literal> files. You should +open them with <filename>/nix/bin/nix-install-package</filename>. +This will open a window that asks you to confirm that you want to +install the package. When you answer <literal>Y</literal>, 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.</para> + +<para>You can also install <literal>application/nix-package</literal> +files from the command line directly. See <xref +linkend='sec-nix-install-package' /> for details.</para> + +</section> + + +<section xml:id="sec-sharing-packages"><title>Sharing packages between machines</title> + +<para>Sometimes 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.</para> + +<para>The command <command +linkend="sec-nix-copy-closure">nix-copy-closure</command> 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: + +<screen> +$ nix-copy-closure --to alice@itchy.example.org $(type -p firefox)</screen> + +See <xref linkend='sec-nix-copy-closure' /> for details.</para> + +<para>With <command linkend='refsec-nix-store-export'>nix-store +--export</command> and <command +linkend='refsec-nix-store-import'>nix-store --import</command> 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, + +<screen> +$ nix-store --export $(nix-store -qR $(type -p firefox)) > firefox.closure</screen> + +writes the closure of Firefox to a file. You can then copy this file +to another machine and install the closure: + +<screen> +$ nix-store --import < firefox.closure</screen> + +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: + +<screen> +$ nix-store --export $(nix-store -qR $(type -p firefox)) | bzip2 | \ + ssh alice@itchy.example.org "bunzip2 | nix-store --import"</screen> + +But note that <command>nix-copy-closure</command> is generally more +efficient in this example because it only copies paths that are not +already present in the target Nix store.</para> + +<para>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 <emphasis>on demand</emphasis>. For instance, +suppose that you mount a remote machine containing a Nix store via +<command +xlink:href="http://fuse.sourceforge.net/sshfs.html">sshfs</command>: + +<screen> +$ sshfs alice@itchy.example.org:/ /mnt</screen> + +You should then set the <envar>NIX_OTHER_STORES</envar> environment +variable to tell Nix about this remote Nix store: + +<screen> +$ export NIX_OTHER_STORES=/mnt/nix</screen> + +Then if you do any Nix operation, e.g. + +<screen> +$ nix-env -i firefox</screen> + +and Nix has to build a path that it sees is already present in +<filename>/mnt/nix</filename>, then it will just copy from there +instead of building it from source.</para> + + +</section> + + +</chapter> |