<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>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>