'... another level of indirection not shown in the figure above ...'
but in the 'user-environments.png' figure there is '~/.nix-profile'.
the figure was updated with the commit: f982df3 on Mar 16, 2005.
		
	
			
		
			
				
	
	
		
			158 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			158 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>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>
 |