1
0
Fork 0
mirror of https://github.com/NixOS/nix-pills synced 2024-09-19 04:00:13 -04:00
nix-pills/pills/01-why-you-should-give-it-try.xml

285 lines
12 KiB
XML
Raw Normal View History

2017-08-11 21:41:14 -04:00
<chapter xmlns="http://docbook.org/ns/docbook"
2017-08-11 18:22:51 -04:00
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
2017-08-12 17:57:17 -04:00
xml:id="why-you-should-give-it-a-try">
2017-08-11 18:22:51 -04:00
2017-08-22 08:19:43 -04:00
<title>Why You Should Give it a Try</title>
2017-08-11 22:47:47 -04:00
<section>
<title>Introduction</title>
<para>
2017-11-07 16:21:39 -05:00
Welcome to the first post of the "<link
xlink:href="https://nixos.org/nix">Nix</link> in pills" series.
Nix is a purely functional package manager and deployment
system for POSIX.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
There's a lot of documentation that describes what Nix, <link
xlink:href="https://nixos.org/nixos">NixOS</link> and related
projects are.
But the purpose of this post is to convince you to give Nix a try.
2017-08-11 22:47:47 -04:00
Installing NixOS is not required, but sometimes I may refer to
NixOS as a real world example of Nix usage for building a whole
operating system.
</para>
</section>
<section>
2017-11-07 16:21:39 -05:00
<title>Rationale for this series</title>
2017-08-11 22:47:47 -04:00
<para>
The <link xlink:href="https://nixos.org/manual/nix">Nix</link>,
<link xlink:href="https://nixos.org/manual/nixpkgs/">Nixpkgs</link>, and
<link xlink:href="https://nixos.org/manual/nixos/">NixOS</link> manuals
along with <link xlink:href="https://nixos.wiki/">the wiki</link> are
excellent resources for explaining how Nix/NixOS works, how
you can use it, and how cool things are being done with it.
2017-11-07 16:21:39 -05:00
However, at the beginning you may feel that some of the magic
which happens behind the scenes is hard to grasp.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
This series aims to complement the existing explanations from the
2017-08-11 22:47:47 -04:00
more formal documents.
</para>
<para>
2017-11-07 16:21:39 -05:00
The following is a description of Nix. Just as with pills, I'll try to be as
2017-08-11 22:47:47 -04:00
short as possible.
</para>
</section>
<section>
2017-11-07 16:21:39 -05:00
<title>Not being purely functional</title>
2017-08-11 22:47:47 -04:00
<para>
Most, if not all, widely used package managers (<link
xlink:href="https://wiki.debian.org/dpkg">dpkg</link>, <link
xlink:href="http://www.rpm.org/">rpm</link>, ...) mutate the
global state of the system. If a package
<literal>foo-1.0</literal> installs a program to
2017-11-18 06:32:07 -05:00
<filename>/usr/bin/foo</filename>, you cannot install
2017-08-11 22:47:47 -04:00
<literal>foo-1.1</literal> as well, unless you change the
installation paths or the binary name.
2017-11-07 16:21:39 -05:00
But changing the binary names means breaking users of
that binary.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
There are some attempts to mitigate this problem.
Debian, for example, partially solves the problem with the
<link
xlink:href="https://wiki.debian.org/DebianAlternatives">alternatives</link>
system.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
So while in theory it's possible with some current systems to install
multiple versions of the same package, in practice it's very
painful.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
Let's say you need an nginx service and also an nginx-openresty
service. You have to create a new package that changes all the
paths to have, for example, an <literal>-openresty</literal> suffix.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
Or suppose that you want to run two different instances of mysql: 5.2 and
5.5. The same thing applies, plus you have to also make sure the two
mysqlclient libraries do not collide.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
This is not impossible but it <emphasis>is</emphasis> very inconvenient.
If you want to install two whole stacks of software like GNOME 3.10 and GNOME
2017-08-11 22:47:47 -04:00
3.12, you can imagine the amount of work.
</para>
<para>
2017-11-07 16:21:39 -05:00
From an administrator's point of view: you can use containers. The
typical solution nowadays is to create a container per service,
2017-09-13 09:15:14 -04:00
especially when different versions are needed. That somewhat
2017-08-11 22:47:47 -04:00
solves the problem, but at a different level and with other
2017-11-07 16:21:39 -05:00
drawbacks. For example, needing orchestration tools, setting up a shared
cache of packages, and new machines to monitor rather than
2017-08-11 22:47:47 -04:00
simple services.
</para>
<para>
2017-11-07 16:21:39 -05:00
From a developer's point of view: you can use virtualenv for python, or jhbuild
for gnome, or whatever else. But then how do you mix the two stacks?
2017-09-13 09:15:14 -04:00
How do you avoid recompiling the same thing when it could
instead be shared? Also you need to set up your development
2017-08-11 22:47:47 -04:00
tools to point to the different directories where libraries are
2017-09-13 09:15:14 -04:00
installed. Not only that, there's the risk that some of the software
2017-08-11 22:47:47 -04:00
incorrectly uses system libraries.
</para>
<para>
And so on. Nix solves all this at the packaging level and
solves it well. A single tool to rule them all.
</para>
</section>
<section>
2017-11-07 16:21:39 -05:00
<title> Being purely functional</title>
2017-08-11 22:47:47 -04:00
<para>
2017-09-13 09:15:14 -04:00
Nix makes no assumptions about the global state of the system.
2017-08-11 22:47:47 -04:00
This has many advantages, but also some drawbacks of course.
2017-11-07 16:21:39 -05:00
The core of a Nix system is the Nix store, usually
2017-11-18 06:32:07 -05:00
installed under <filename>/nix/store</filename>, and some tools to manipulate the
2017-11-07 16:21:39 -05:00
store. In Nix there is the notion of a <emphasis>derivation</emphasis> rather than a
package. The difference can be subtle at the beginning, so I
will often use the words interchangeably.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
Derivations/packages are stored in the Nix store as follows:
2017-11-18 06:32:07 -05:00
<filename>/nix/store/<replaceable>hash-name</replaceable></filename>,
2017-11-07 16:21:39 -05:00
where the hash uniquely identifies the derivation (this isn't quite true,
it's a little more complex), and the name is the name of
2017-08-11 22:47:47 -04:00
the derivation.
</para>
<para>
2017-11-07 16:21:39 -05:00
Let's take a bash derivation as an example:
2017-11-18 06:32:07 -05:00
<filename>/nix/store/s4zia7hhqkin1di0f187b79sa2srhv6k-bash-4.2-p45/</filename>.
This is a directory in the Nix store which contains <filename>bin/bash</filename>.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-18 06:32:07 -05:00
What that means is that there's no <filename>/bin/bash</filename>, there's only that
2017-11-07 16:21:39 -05:00
self-contained build output in the store. The same goes for
coreutils and everything else. To make them convenient
to use from the shell, Nix will arrange for binaries to appear in
your <varname>PATH</varname> as appropriate.
2017-08-11 22:47:47 -04:00
</para>
<para>
What we have is basically a store of all packages (with different versions
2017-11-07 16:21:39 -05:00
occupying different locations), and everything in the Nix store is immutable.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
In fact, there's no ldconfig cache either. So where does bash find libc?
2017-08-11 22:47:47 -04:00
</para>
<screen><xi:include href="./01/which-bash.txt" parse="text" /></screen>
<para>
2017-11-07 16:21:39 -05:00
It turns out that when bash was built, it was built against that specific
version of glibc in the Nix store, and at runtime it will require exactly that
2017-08-11 22:47:47 -04:00
glibc version.
</para>
<para>
2017-11-07 16:21:39 -05:00
Don't be confused by the version in the derivation name:
it's only a name for us humans. You may end up having two derivations with
the same name but different hashes: it's the hash that really matters.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
What does all this mean? It means that you could run mysql 5.2 with glibc-2.18,
2017-08-11 22:47:47 -04:00
and mysql 5.5 with glibc-2.19. You could use your python module
with python 2.7 compiled with gcc 4.6 and the same python
module with python 3 compiled with gcc 4.8, all in the same
system.
</para>
<para>
2017-11-07 16:21:39 -05:00
In other words: no dependency hell, not even a dependency
2017-08-11 22:47:47 -04:00
resolution algorithm. Straight dependencies from derivations to
other derivations.
</para>
<para>
2017-11-07 16:21:39 -05:00
From an administrator's point of view: if you want an old PHP version for
one application, but want to upgrade the rest of the system, that's not painful any more.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
From a developer's point of view: if you want to develop webkit with llvm
3.4 and 3.3, that's not painful any more.
2017-08-11 22:47:47 -04:00
</para>
</section>
<section>
2017-11-07 16:21:39 -05:00
<title>Mutable vs. immutable</title>
2017-08-11 22:47:47 -04:00
<para>
2017-11-07 16:21:39 -05:00
When upgrading a library, most package managers replace it in-place.
2017-08-11 22:47:47 -04:00
All new applications run afterwards with the new library
without being recompiled. After all, they all refer dynamically
2017-11-18 06:32:07 -05:00
to <filename>libc6.so</filename>.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-11-07 16:21:39 -05:00
Since Nix derivations are immutable, upgrading a library like glibc
2017-08-11 22:47:47 -04:00
means recompiling all applications, because the glibc path to
2017-11-07 16:21:39 -05:00
the Nix store has been hardcoded.
2017-08-11 22:47:47 -04:00
</para>
<para>
So how do we deal with security updates? In Nix we have some
2017-09-13 09:15:14 -04:00
tricks (still pure) to solve this problem, but that's another
2017-08-11 22:47:47 -04:00
story.
</para>
<para>
Another problem is that unless software has in mind a pure
2017-11-07 16:21:39 -05:00
functional model, or can be adapted to it, it can be hard to compose
2017-08-11 22:47:47 -04:00
applications at runtime.
</para>
<para>
2017-11-07 16:21:39 -05:00
Let's take Firefox for example. On most systems, you install flash,
and it starts working in Firefox because Firefox looks in a global path for plugins.
2017-08-11 22:47:47 -04:00
</para>
<para>
In Nix, there's no such global path for plugins. Firefox
2017-11-07 16:21:39 -05:00
therefore must know explicitly about the path to flash. The way
we handle this problem is to wrap
the Firefox binary so that we can setup the necessary environment to make
it find flash in the nix store. That will produce a new Firefox
2017-09-13 09:15:14 -04:00
derivation: be aware that it takes a few seconds, and it makes
2017-08-11 22:47:47 -04:00
composition harder at runtime.
</para>
<para>
2017-11-07 16:21:39 -05:00
There are no upgrade/downgrade scripts for your data. It doesn't make
2017-08-11 22:47:47 -04:00
sense with this approach, because there's no real derivation to
2017-11-07 16:21:39 -05:00
be upgraded. With Nix you switch to using other software with
2017-08-11 22:47:47 -04:00
its own stack of dependencies, but there's no formal notion of
upgrade or downgrade when doing so.
</para>
<para>
2017-11-07 16:21:39 -05:00
If there is a data format change, then migrating to the new data format remains
your own responsibility.
2017-08-11 22:47:47 -04:00
</para>
</section>
<section>
<title>Conclusion</title>
<para>
Nix lets you compose software at build time with maximum
2017-11-07 16:21:39 -05:00
flexibility, and with builds being as reproducible as possible.
2017-09-13 09:15:14 -04:00
Not only that, due to its nature deploying systems in the cloud is
2017-11-07 16:21:39 -05:00
so easy, consistent, and reliable that in the Nix world all
2017-08-11 22:47:47 -04:00
existing self-containment and orchestration tools are
2017-11-07 16:21:39 -05:00
deprecated by <link xlink:href="http://nixos.org/nixops/">NixOps</link>.
2017-08-11 22:47:47 -04:00
</para>
<para>
2017-09-13 09:15:14 -04:00
It however <emphasis>currently</emphasis> falls short when
2017-11-07 16:21:39 -05:00
working with dynamic composition at runtime or replacing low
level libraries, due to the need to rebuild dependencies.
2017-08-11 22:47:47 -04:00
</para>
<para>
That may sound scary, however after running NixOS on both a
server and a laptop desktop, I'm very satisfied so far. Some of
2017-11-07 16:21:39 -05:00
the architectural problems just need some man-power, other
2017-09-13 09:15:14 -04:00
design problems still need to be solved as a community.
2017-08-11 22:47:47 -04:00
</para>
<para>
Considering <link
xlink:href="https://nixos.org/nixpkgs/">Nixpkgs</link> (<link
xlink:href="https://github.com/NixOS/nixpkgs">github
link</link>) is a completely new repository of all the existing
software, with a completely fresh concept, and with few core
developers but overall year-over-year increasing contributions,
2017-09-13 09:15:14 -04:00
the current state is more than acceptable and beyond the
2017-08-11 22:47:47 -04:00
experimental stage. In other words, it's worth your investment.
</para>
</section>
<section>
<title>Next pill...</title>
<para>
...we will install Nix on top of your current system (I assume
GNU/Linux, but we also have OSX users) and start inspecting the
2017-11-07 16:21:39 -05:00
installed software.
2017-08-11 22:47:47 -04:00
</para>
</section>
2017-08-11 21:41:14 -04:00
</chapter>