forked from lix-project/lix
eb53f592b8
Closes #415.
160 lines
6.7 KiB
XML
160 lines
6.7 KiB
XML
<chapter xmlns="http://docbook.org/ns/docbook"
|
||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||
version="5.0"
|
||
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 firefox</screen>
|
||
|
||
on a set of Nix expressions that contained Firefox 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>
|
||
|
||
</chapter>
|