2014-08-27 16:41:09 +00:00
|
|
|
|
<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 —
|
2020-07-23 12:16:46 +00:00
|
|
|
|
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. Here is what a part
|
|
|
|
|
of a typical Nix store looks like:</para>
|
2014-08-27 16:41:09 +00:00
|
|
|
|
|
2020-07-23 12:16:46 +00:00
|
|
|
|
<mediaobject>
|
|
|
|
|
<imageobject>
|
|
|
|
|
<imagedata fileref='../figures/user-environments.png' format='PNG' />
|
|
|
|
|
</imageobject>
|
|
|
|
|
</mediaobject>
|
2014-08-27 16:41:09 +00:00
|
|
|
|
|
|
|
|
|
<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
|
2020-07-23 08:38:19 +00:00
|
|
|
|
<literal>PATH</literal> environment variable to include the
|
2014-08-27 16:41:09 +00:00
|
|
|
|
<filename>bin</filename> directory of every package we want to use,
|
2020-07-23 08:38:19 +00:00
|
|
|
|
but this is not very convenient since changing <literal>PATH</literal>
|
2014-08-27 16:41:09 +00:00
|
|
|
|
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
|
2020-07-23 12:16:46 +00:00
|
|
|
|
instance, in the figure above, 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
|
2014-08-27 16:41:09 +00:00
|
|
|
|
|
|
|
|
|
<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>
|
2014-12-13 22:16:08 +00:00
|
|
|
|
$ nix-env -i subversion firefox</screen>
|
2014-08-27 16:41:09 +00:00
|
|
|
|
|
2014-12-13 22:16:08 +00:00
|
|
|
|
on a set of Nix expressions that contained Firefox and a new version
|
2014-08-27 16:41:09 +00:00
|
|
|
|
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>
|
|
|
|
|
|
2015-01-05 12:31:06 +00:00
|
|
|
|
<para>You generally wouldn’t have
|
2020-07-23 12:28:05 +00:00
|
|
|
|
<filename>/nix/var/nix/profiles/<emphasis>some-profile</emphasis>/bin</filename>
|
2020-07-23 08:38:19 +00:00
|
|
|
|
in your <literal>PATH</literal>. Rather, there is a symlink
|
2014-08-27 16:41:09 +00:00
|
|
|
|
<filename>~/.nix-profile</filename> that points to your current
|
|
|
|
|
profile. This means that you should put
|
2020-07-23 08:38:19 +00:00
|
|
|
|
<filename>~/.nix-profile/bin</filename> in your <literal>PATH</literal>
|
2014-08-27 16:41:09 +00:00
|
|
|
|
(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>
|
|
|
|
|
|
2014-12-13 22:16:08 +00:00
|
|
|
|
</chapter>
|