forked from lix-project/lix
* Better introduction.
* Set notes in a different color than warnings.
This commit is contained in:
parent
1317242780
commit
2b20701f78
|
@ -5,51 +5,123 @@ has grown to 5, with more expected.</quote></para></epigraph>
|
||||||
|
|
||||||
<para>Nix is a system for the deployment of software. Software
|
<para>Nix is a system for the deployment of software. Software
|
||||||
deployment is concerned with the creation, distribution, and
|
deployment is concerned with the creation, distribution, and
|
||||||
management of software components (<quote>packages</quote>). There
|
management of software components (<quote>packages</quote>). Its main
|
||||||
are many tools for this, but they tend to ignore some important
|
features are:
|
||||||
requirements for deployment:
|
|
||||||
|
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
|
|
||||||
<listitem><para><emphasis>Correctness</emphasis>. The basic goal of
|
<listitem><para>It makes sure that dependency specifications are
|
||||||
software deployment is to transfer software from one machine (e.g.,
|
complete. In general in a deployment system you have to specify for
|
||||||
the developer's, where it presumably works) to another machine (e.g.,
|
each component what its dependencies are, but there are no guarantees
|
||||||
the end user's). The software should work exactly the same on the
|
that this specification is complete. If you forget a dependency, then
|
||||||
target machine as on the source machine. But this in practice turns
|
the component will build and work correctly on
|
||||||
out to be rather difficult due to <emphasis>dependencies between
|
<emphasis>your</emphasis> machine if you have the dependency
|
||||||
components</emphasis> and <emphasis>interference between
|
installed, but not on the end user's machine if it's not
|
||||||
components</emphasis>. If we deploy a component that depends on other
|
there.</para></listitem>
|
||||||
components, then we should deploy those dependencies as well. If they
|
|
||||||
are missing on the target system, the component probably won't work.
|
|
||||||
If they <emphasis>are</emphasis> present but are not the right
|
|
||||||
version, the component might not work. And if even if they are the
|
|
||||||
right version, they may have been built with different flags or
|
|
||||||
options, which can cause incompatibilities. Interference occurs when
|
|
||||||
components <quote>collide</quote> with each other in the file system.
|
|
||||||
For instance, different versions of the same package tend to overwrite
|
|
||||||
each other, so they cannot be installed at the same time. But always
|
|
||||||
picking the latest version might break components that only work with
|
|
||||||
some older version.</para></listitem>
|
|
||||||
|
|
||||||
<listitem><para><emphasis>Variability</emphasis>. Many package
|
<listitem><para>It is possible to have <emphasis>multiple versions or
|
||||||
management tools have difficulty supporting the installation of
|
variants</emphasis> of a component installed at the same time. In
|
||||||
multiple versions or variants of the same component. This is bad
|
contrast, in systems such as RPM different versions of the same
|
||||||
because as ...</para></listitem>
|
package tend to install to the same location in the file system, so
|
||||||
|
you installing one version will remove the other. This is especially
|
||||||
|
important if you want to have use applications that have conflicting
|
||||||
|
requirements on different versions of a component (e.g., application A
|
||||||
|
requires version 1.0 of library X, while application B requires a
|
||||||
|
non-backwards compatible version 1.1).</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Users can have different <quote>views</quote>
|
||||||
|
(<quote>profiles</quote> in Nix parlance) on the set of installed
|
||||||
|
applications in a system. For instance, one user can have version 1.0
|
||||||
|
of some package visible, while another is using version 1.1, and a
|
||||||
|
third doesn't use it at all.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>It is possible to atomically
|
||||||
|
<emphasis>upgrade</emphasis> software. I.e., there is no time window
|
||||||
|
during an upgrade in which part of the old version and part of the new
|
||||||
|
version are simultaneously visible (which might well cause the
|
||||||
|
component to fail).</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Likewise, it is possible to atomically roll-back after
|
||||||
|
an install, upgrade, or uninstall action. That is, in a fast (O(1))
|
||||||
|
operation the previous configuration of the system will be
|
||||||
|
restored. This is because upgrade or uninstall actions doesn't
|
||||||
|
actually remove components from the system.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Unused components can be
|
||||||
|
<emphasis>garbage-collected</emphasis> automatically and safely.
|
||||||
|
I.e., when you remove an application from a profile, its dependencies
|
||||||
|
will be deleted by the garbage collector if there are no other active
|
||||||
|
applications that are using it.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Nix supports both source-based deployment models
|
||||||
|
(where you distribute <emphasis>Nix expressions</emphasis> that tell
|
||||||
|
Nix how to build software from source) and binary-based deployment
|
||||||
|
models. The latter is more-or-less transparent: installation of
|
||||||
|
components is always based on Nix expressions, but if those
|
||||||
|
expressions have been built before and Nix knows that the resulting
|
||||||
|
binaries are available somewhere, it will use those
|
||||||
|
instead.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Nix is flexible in the deployment policies that it
|
||||||
|
supports. There is a clear separation between the tools that
|
||||||
|
implement basic Nix <emphasis>mechanisms</emphasis> (e.g., building
|
||||||
|
Nix expressions), and the tools that implement various deployment
|
||||||
|
<emphasis>policies</emphasis>. For instance, there is a concept of
|
||||||
|
<quote>Nix channels</quote> that can be used to keep software
|
||||||
|
installations up-to-date automatically from a network source. This is
|
||||||
|
a policy that is implemented by a fairly short Perl script, which can
|
||||||
|
be adapted easily to achieve similar policies.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Nix component builds aim to be <quote>pure</quote>;
|
||||||
|
that is, unaffected by anything other than the declared dependencies.
|
||||||
|
This means that if a component was built succesfully once, it can be
|
||||||
|
rebuilt again on another machine and the result will be the same. We
|
||||||
|
cannot <emphasis>guarantee</emphasis> this (e.g., if the build depends
|
||||||
|
on the time-of-day), but Nix (and the tools in the Nix Packages
|
||||||
|
collection) takes special measures to help achieve
|
||||||
|
this.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Nix expressions (the things that tell Nix how to build
|
||||||
|
components) are self-contained: they describe not just components but
|
||||||
|
complete compositions. In other words, Nix expressions also describe
|
||||||
|
how to build all the dependencies. This is contrast to component
|
||||||
|
specification languages like RPM spec files, which might say that a
|
||||||
|
component X depends on some other component Y, but since it does not
|
||||||
|
describe <emphasis>exactly</emphasis> what Y is, the result of
|
||||||
|
building or running X might be different on different machines.
|
||||||
|
Combined with purity, self-containedness ensures that a component that
|
||||||
|
<quote>works</quote> on one machine also works on another, when
|
||||||
|
deployed using Nix.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>The Nix expression language makes it easy to describe
|
||||||
|
variability in components (e.g., optional features or
|
||||||
|
dependencies).</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Nix is ideal for building build farms that do
|
||||||
|
continuous builds of software from a version management system, since
|
||||||
|
it can take care of building all the dependencies as well. Also, Nix
|
||||||
|
only rebuilds components that have changed, so there are no
|
||||||
|
unnecessary builds. In addition, Nix can transparently distribute
|
||||||
|
build jobs over different machines, including different
|
||||||
|
platforms.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Nix can be used not only for software deployment, but
|
||||||
|
also for <emphasis>service deployment</emphasis>, such as the
|
||||||
|
deployment of a complete web server with all its configuration files,
|
||||||
|
static pages, software dependencies, and so on. Nix's advantages for
|
||||||
|
software deployment also apply here, for instance, the ability
|
||||||
|
trivially to have multiple configurations at the same time, or the
|
||||||
|
ability to do roll-backs.</para></listitem>
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>Here are some of Nix's main features:
|
<para>This manual tells you how to install and use Nix and how to
|
||||||
|
write Nix expressions for software not already in the Nix Packages
|
||||||
<itemizedlist>
|
collection. It also discusses some advanced topics, such as setting
|
||||||
|
up a Nix-based build farm, and doing service deployment using
|
||||||
<listitem><para>Nix can quite reliably figure out the dependencies
|
Nix.</para>
|
||||||
between components.</para></listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<warning><para>This manual is a work in progress. It's quite likely
|
<warning><para>This manual is a work in progress. It's quite likely
|
||||||
to be incomplete, inconsistent with the current implementation, or
|
to be incomplete, inconsistent with the current implementation, or
|
||||||
|
@ -62,85 +134,10 @@ a Memory Management Discipline on Software
|
||||||
Deployment</citetitle></ulink> discusses the hashing mechanism used to
|
Deployment</citetitle></ulink> discusses the hashing mechanism used to
|
||||||
ensure reliable dependency identification and non-interference between
|
ensure reliable dependency identification and non-interference between
|
||||||
different versions and variants of packages. The LISA 2004 paper
|
different versions and variants of packages. The LISA 2004 paper
|
||||||
<citetitle>Nix: A Safe and Policy-Free System for Software
|
<ulink
|
||||||
Deployment</citetitle> gives a more general discussion of Nix from a
|
url='http://www.cs.uu.nl/~eelco/pubs/nspfssd-lisa2004-final.pdf'><citetitle>Nix:
|
||||||
system-administration perspective.</para></note>
|
A Safe and Policy-Free System for Software
|
||||||
|
Deployment</citetitle></ulink> gives a more general discussion of Nix
|
||||||
<para>
|
from a system-administration perspective.</para></note>
|
||||||
Nix solves some large problems that exist in most current deployment and
|
|
||||||
package management systems. <emphasis>Dependency determination</emphasis>
|
|
||||||
is a big one: the correct installation of a software component requires
|
|
||||||
that all dependencies of that component (i.e., other components used by it)
|
|
||||||
are also installed. Most systems have no way to verify that the specified
|
|
||||||
dependencies of a component are actually sufficient.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Another big problem is the lack of support for concurrent availability of
|
|
||||||
multiple <emphasis>variants</emphasis> of a component. It must be possible
|
|
||||||
to have several versions of a component installed at the same time, or
|
|
||||||
several instances of the same version built with different parameters.
|
|
||||||
Unfortunately, components are in general not properly isolated from each
|
|
||||||
other. For instance, upgrading a component that is a dependency for some
|
|
||||||
other component might break the latter.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Nix solves these problems by building and storing packages in paths that
|
|
||||||
are infeasible to predict in advance. For example, the artifacts of a
|
|
||||||
package <literal>X</literal> might be stored in
|
|
||||||
<filename>/nix/store/d58a0606ed616820de291d594602665d-X</filename>, rather
|
|
||||||
than in, say, <filename>/usr/lib</filename>. The path component
|
|
||||||
<filename>d58a...</filename> is actually a cryptographic hash of all the
|
|
||||||
inputs (i.e., sources, requisites, and build flags) used in building
|
|
||||||
<literal>X</literal>, and as such is very fragile: any change to the inputs
|
|
||||||
will change the hash. Therefore it is not sensible to
|
|
||||||
<emphasis>hard-code</emphasis> such a path into the build scripts of a
|
|
||||||
package <literal>Y</literal> that uses <literal>X</literal> (as does happen
|
|
||||||
with <quote>fixed</quote> paths such as <filename>/usr/lib</filename>).
|
|
||||||
Rather, the build script of package <literal>Y</literal> is parameterised
|
|
||||||
with the actual location of <literal>X</literal>, which is supplied by the
|
|
||||||
Nix system.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
As stated above, the path name of a file system object contain a
|
|
||||||
cryptographic hash of all inputs involved in building it. A change to any
|
|
||||||
of the inputs will cause the hash to change--and by extension, the path
|
|
||||||
name. These inputs include both sources (variation in time) and
|
|
||||||
configuration options (variation in space). Therefore variants of the same
|
|
||||||
package don't clash---they can co-exist peacefully within the same file
|
|
||||||
system.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Other features:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<emphasis>Transparent source/binary deployment.</emphasis>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<emphasis>Unambiguous identification of configuration.</emphasis>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<emphasis>Automatic storage management.</emphasis>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<emphasis>Atomic upgrades and rollbacks.</emphasis>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<emphasis>Support for many simultaneous configurations.</emphasis>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<emphasis>Portability.</emphasis> Nix is quite portable. Contrary to
|
|
||||||
build systems like those in, e.g., Vesta and ClearCase, it does not rely on
|
|
||||||
operating system extensions.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
]>
|
]>
|
||||||
|
|
||||||
<book>
|
<book>
|
||||||
<title>Nix: A System for Software Deployment</title>
|
<title>Nix User's Guide</title>
|
||||||
|
|
||||||
<subtitle>Draft (Version &version;)</subtitle>
|
<subtitle>Draft (Version &version;)</subtitle>
|
||||||
|
|
||||||
|
|
|
@ -112,10 +112,16 @@ div.note,div.warning
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.note h3,div.warning h3
|
div.warning h3
|
||||||
{
|
{
|
||||||
color: red;
|
color: red;
|
||||||
text-decoration: underline;
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.note h3
|
||||||
|
{
|
||||||
|
color: blue;
|
||||||
|
font-size: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.navfooter *
|
div.navfooter *
|
||||||
|
|
Loading…
Reference in a new issue