2ef8f0608c
While trying to understand garbage collection it was not immediately clear that only the runtime dependency closure of output paths would be kept (instead of the build-time dependency closure). This commit attempts to clarify this by expanding some of the glossary definitions and extending the Garbage Collection section.
274 lines
9.6 KiB
XML
274 lines
9.6 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="ch-about-nix">
|
||
|
||
<title>About Nix</title>
|
||
|
||
<para>Nix is a <emphasis>purely functional package manager</emphasis>.
|
||
This means that it treats packages like values in purely functional
|
||
programming languages such as Haskell — they are built by functions
|
||
that don’t have side-effects, and they never change after they have
|
||
been built. Nix stores packages in the <emphasis>Nix
|
||
store</emphasis>, usually the directory
|
||
<filename>/nix/store</filename>, where each package has its own unique
|
||
subdirectory such as
|
||
|
||
<programlisting>
|
||
/nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1/
|
||
</programlisting>
|
||
|
||
where <literal>b6gvzjyb2pg0…</literal> is a unique identifier for the
|
||
package that captures all its dependencies (it’s a cryptographic hash
|
||
of the package’s build dependency graph). This enables many powerful
|
||
features.</para>
|
||
|
||
|
||
<simplesect><title>Multiple versions</title>
|
||
|
||
<para>You can have multiple versions or variants of a package
|
||
installed at the same time. This is especially important when
|
||
different applications have dependencies on different versions of the
|
||
same package — it prevents the “DLL hell”. Because of the hashing
|
||
scheme, different versions of a package end up in different paths in
|
||
the Nix store, so they don’t interfere with each other.</para>
|
||
|
||
<para>An important consequence is that operations like upgrading or
|
||
uninstalling an application cannot break other applications, since
|
||
these operations never “destructively” update or delete files that are
|
||
used by other packages.</para>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>Complete dependencies</title>
|
||
|
||
<para>Nix helps you make sure that package dependency specifications
|
||
are complete. In general, when you’re making a package for a package
|
||
management system like RPM, you have to specify for each package what
|
||
its dependencies are, but there are no guarantees that this
|
||
specification is complete. If you forget a dependency, then the
|
||
package will build and work correctly on <emphasis>your</emphasis>
|
||
machine if you have the dependency installed, but not on the end
|
||
user's machine if it's not there.</para>
|
||
|
||
<para>Since Nix on the other hand doesn’t install packages in “global”
|
||
locations like <filename>/usr/bin</filename> but in package-specific
|
||
directories, the risk of incomplete dependencies is greatly reduced.
|
||
This is because tools such as compilers don’t search in per-packages
|
||
directories such as
|
||
<filename>/nix/store/5lbfaxb722zp…-openssl-0.9.8d/include</filename>,
|
||
so if a package builds correctly on your system, this is because you
|
||
specified the dependency explicitly. This takes care of the build-time
|
||
dependencies.</para>
|
||
|
||
<para>Once a package is built, runtime dependencies are found by
|
||
scanning binaries for the hash parts of Nix store paths (such as
|
||
<literal>r8vvq9kq…</literal>). This sounds risky, but it works
|
||
extremely well.</para>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>Multi-user support</title>
|
||
|
||
<para>Nix has multi-user support. This means that non-privileged
|
||
users can securely install software. Each user can have a different
|
||
<emphasis>profile</emphasis>, a set of packages in the Nix store that
|
||
appear in the user’s <envar>PATH</envar>. If a user installs a
|
||
package that another user has already installed previously, the
|
||
package won’t be built or downloaded a second time. At the same time,
|
||
it is not possible for one user to inject a Trojan horse into a
|
||
package that might be used by another user.</para>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>Atomic upgrades and rollbacks</title>
|
||
|
||
<para>Since package management operations never overwrite packages in
|
||
the Nix store but just add new versions in different paths, they are
|
||
<emphasis>atomic</emphasis>. So during a package upgrade, there is no
|
||
time window in which the package has some files from the old version
|
||
and some files from the new version — which would be bad because a
|
||
program might well crash if it’s started during that period.</para>
|
||
|
||
<para>And since packages aren’t overwritten, the old versions are still
|
||
there after an upgrade. This means that you can <emphasis>roll
|
||
back</emphasis> to the old version:</para>
|
||
|
||
<screen>
|
||
$ nix-env --upgrade <replaceable>some-packages</replaceable>
|
||
$ nix-env --rollback
|
||
</screen>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>Garbage collection</title>
|
||
|
||
<para>When you uninstall a package like this…
|
||
|
||
<screen>
|
||
$ nix-env --uninstall firefox
|
||
</screen>
|
||
|
||
the package isn’t deleted from the system right away (after all, you
|
||
might want to do a rollback, or it might be in the profiles of other
|
||
users). Instead, unused packages can be deleted safely by running the
|
||
<emphasis>garbage collector</emphasis>:
|
||
|
||
<screen>
|
||
$ nix-collect-garbage
|
||
</screen>
|
||
|
||
This deletes all packages that aren’t in use by any user profile or by
|
||
a currently running program.</para>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>Functional package language</title>
|
||
|
||
<para>Packages are built from <emphasis>Nix expressions</emphasis>,
|
||
which is a simple functional language. A Nix expression describes
|
||
everything that goes into a package build action (a “derivation”):
|
||
other packages, sources, the build script, environment variables for
|
||
the build script, etc. Nix tries very hard to ensure that Nix
|
||
expressions are <emphasis>deterministic</emphasis>: building a Nix
|
||
expression twice should yield the same result.</para>
|
||
|
||
<para>Because it’s a functional language, it’s easy to support
|
||
building variants of a package: turn the Nix expression into a
|
||
function and call it any number of times with the appropriate
|
||
arguments. Due to the hashing scheme, variants don’t conflict with
|
||
each other in the Nix store.</para>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>Transparent source/binary deployment</title>
|
||
|
||
<para>Nix expressions generally describe how to build a package from
|
||
source, so an installation action like
|
||
|
||
<screen>
|
||
$ nix-env --install firefox
|
||
</screen>
|
||
|
||
<emphasis>could</emphasis> cause quite a bit of build activity, as not
|
||
only Firefox but also all its dependencies (all the way up to the C
|
||
library and the compiler) would have to built, at least if they are
|
||
not already in the Nix store. This is a <emphasis>source deployment
|
||
model</emphasis>. For most users, building from source is not very
|
||
pleasant as it takes far too long. However, Nix can automatically
|
||
skip building from source and instead use a <emphasis>binary
|
||
cache</emphasis>, a web server that provides pre-built binaries. For
|
||
instance, when asked to build
|
||
<literal>/nix/store/b6gvzjyb2pg0…-firefox-33.1</literal> from source,
|
||
Nix would first check if the file
|
||
<uri>https://cache.nixos.org/b6gvzjyb2pg0….narinfo</uri> exists, and
|
||
if so, fetch the pre-built binary referenced from there; otherwise, it
|
||
would fall back to building from source.</para>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<!--
|
||
<simplesect><title>Binary patching</title>
|
||
|
||
<para>In addition to downloading binaries automatically if they’re
|
||
available, Nix can download binary deltas that patch an existing
|
||
package in the Nix store into a new version. This speeds up
|
||
upgrades.</para>
|
||
|
||
</simplesect>
|
||
-->
|
||
|
||
|
||
<simplesect><title>Nix Packages collection</title>
|
||
|
||
<para>We provide a large set of Nix expressions containing hundreds of
|
||
existing Unix packages, the <emphasis>Nix Packages
|
||
collection</emphasis> (Nixpkgs).</para>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>Managing build environments</title>
|
||
|
||
<para>Nix is extremely useful for developers as it makes it easy to
|
||
automatically set up the build environment for a package. Given a
|
||
Nix expression that describes the dependencies of your package, the
|
||
command <command>nix-shell</command> will build or download those
|
||
dependencies if they’re not already in your Nix store, and then start
|
||
a Bash shell in which all necessary environment variables (such as
|
||
compiler search paths) are set.</para>
|
||
|
||
<para>For example, the following command gets all dependencies of the
|
||
Pan newsreader, as described by <link
|
||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/newsreaders/pan/default.nix">its
|
||
Nix expression</link>:</para>
|
||
|
||
<screen>
|
||
$ nix-shell '<nixpkgs>' -A pan
|
||
</screen>
|
||
|
||
<para>You’re then dropped into a shell where you can edit, build and test
|
||
the package:</para>
|
||
|
||
<screen>
|
||
[nix-shell]$ tar xf $src
|
||
[nix-shell]$ cd pan-*
|
||
[nix-shell]$ ./configure
|
||
[nix-shell]$ make
|
||
[nix-shell]$ ./pan/gui/pan
|
||
</screen>
|
||
|
||
<!--
|
||
<para>Since Nix packages are reproducible and have complete dependency
|
||
specifications, Nix makes an excellent basis for <a
|
||
href="[%root%]hydra">a continuous build system</a>.</para>
|
||
-->
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>Portability</title>
|
||
|
||
<para>Nix runs on Linux and macOS.</para>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>NixOS</title>
|
||
|
||
<para>NixOS is a Linux distribution based on Nix. It uses Nix not
|
||
just for package management but also to manage the system
|
||
configuration (e.g., to build configuration files in
|
||
<filename>/etc</filename>). This means, among other things, that it
|
||
is easy to roll back the entire configuration of the system to an
|
||
earlier state. Also, users can install software without root
|
||
privileges. For more information and downloads, see the <link
|
||
xlink:href="http://nixos.org/">NixOS homepage</link>.</para>
|
||
|
||
</simplesect>
|
||
|
||
|
||
<simplesect><title>License</title>
|
||
|
||
<para>Nix is released under the terms of the <link
|
||
xlink:href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">GNU
|
||
LGPLv2.1 or (at your option) any later version</link>.</para>
|
||
|
||
<para>Nix uses the <link
|
||
xlink:href="https://github.com/arangodb/linenoise-ng">linenoise-ng
|
||
library</link>, which has the following license:</para>
|
||
|
||
<programlisting><xi:include href="../../../src/linenoise/LICENSE" parse="text" /></programlisting>
|
||
|
||
</simplesect>
|
||
|
||
|
||
</chapter>
|