[Nix-dev] Proposal: Standard installation procedure

Ertugrul Söylemez ertesx at gmx.de
Thu Oct 16 13:00:57 CEST 2014


Hi there fellow Nixers,

I'd like to propose an installation standard that would make it a lot
easier and more reliable to deploy NixOS to virtual and container-based
systems, including qemu, LXC and Docker.  As a nice side effect it would
greatly simplify most NixOS tools, including nixos-install and
nixos-rebuild.

First of all:  Yes, I'm aware of Nixops, and I don't want to use it for
various reasons.  Currently I'm using my own variant of
make-system-tarball.nix (really just to avoid the expensive and in my
case unnecessary compression step) together with a bunch of Makefiles.
It's a mess and the sooner I can dispense with it, the better.


Proposal
========

The basic idea is this:  To build a system, you use a standard function
from Nixpkgs and pass it a configuration module.  The result is a
derivation that represents a complete self-contained system.  The
initialisation program ($out/init) is not systemd directly, but a script
that first checks whether the filesystem has already been initialised.
If not, it sets up all necessary directories (like /etc) and then starts
systemd as normal.

In other words a container-based NixOS system is really just a Nix
store, nothing more.  It doesn't need to contain any additional files or
directories and building it does not require us to understand the
complexity of nixos-install, because it will all be moved to the system
initialisation phase.  Ideally we should factor out the initialisation
into a separate script $out/pre-init that accepts a prefix argument.
Then $out/init would simply look like this:

    #! /bin/sh
    /nix/store/abcxyz-nixos/pre-init --prefix=/
    exec /nix/store/abc123-systemd/bin/systemd

If we can also move pre-boot initialisation (like installing the boot
loader) into the system itself (say, $out/pre-boot), then we could build
entire virtual machines completely without relying on a hypervisor and
the complexity of having to communicate with the installation process.
Just set up the disk image, install the system and use the resulting
$out/pre-boot script with appropriate override arguments:

    out=`nix-build my-machine.nix`
    # ... copy the closure ...
    $out/pre-boot --override-grub-device=disk.img

This would greatly simplify the implementation of nixos-install (just
build the system and invoke the pre-boot script without overrides), but
more importantly it would provide a very simple and standardised
installation procedure for virtual machines and containers that we can
rely on.


How to use it
=============

Create a file that defines the system derivation (build-system.nix
contains a currently hypothetical function that we would implement as
part of this proposal):

    # my-machine.nix
    let cfg = {config, pkgs, ...}: ...;
    in import <nixos/build-system.nix> cfg

To build the system, we simply use nix-build:

    % nix-build my-machine.nix
    /nix/store/abcxyz-nixos

It is now very easy to create the filesystem for the container.  Just
copy the full closure of the derivation and point the container driver
to the proper initialisation script (or link /sbin/init to it).


Liberated system environments
=============================

Another advantage of this proposal is that we can easily put those
builds in a local user environment and copy only the closure to the
containers (I use *non-remote* containers a lot).  We can even update
them off-line.  That prevents a lot of duplication, because the
containers can be garbage-collected after every change and will contain
only the bare minimum required for operation.  The actual history is
saved on a separate management machine and uses sharing where
appropriate.

In fact we could switch multiple VMs on multiple hosts almost fully
transactionally.  Build and upload everything, then tell every machine
to switch.  Finally update the environment and collect garbage on the
target machines.

Updating the local system would follow the same scheme, so even
nixos-rebuild would become very simple.


Final remarks
=============

The main point of this is that it becomes really easy to reliably
implement something like a custom nixos-install, a remote nixos-rebuild,
Nixops or even make-system-tarball.nix.  No deep knowledge is required
and the instructions and relevant information can be put on a fairly
simple wiki page.

What do you think?  I would love to provide a prototype, but I really
need help with this one.


Greets,
Ertugrul

-- 
Ertugrul Söylemez <ertesx at gmx.de>

Key-ID: F9B5212A
Fingerprint: 8D89 7AC9 21CF F868 F074  9058 30CB D56F F9B5 212A


More information about the nix-dev mailing list