Building secure images with NixOS
Image-based Linux distributions have seen increasing popularity, recently. They promise reliability and security, but pose packaging problems for existing distributions. Ryan Lahfa and Niklas Sturm spoke about the work that NixOS has done to enable an image-based workflow at this year's All Systems Go! conference in Berlin. Unfortunately, LWN was not able to cover the conference for scheduling reasons, but the videos of the event are available for anyone interested in watching the talks. Lahfa and Sturm explained that it is currently possible to create a NixOS system that cryptographically verifies the kernel, initrd, and Nix store on boot — although doing so still has some rough edges. Making an image-based NixOS installation is similarly possible.
Lahfa started by giving a brief overview of NixOS for those attendees who were unfamiliar with it. He described the distribution as a ""standard systemd-based Linux"", but with some differences mostly centered around the fact that it does not follow the filesystem hierarchy standard. In NixOS, all of the binaries on the system live in /nix/store, and are configured to use a path and library path that are tightly scoped to only their declared dependencies. This has a lot of benefits, Lahfa said, including NixOS's ability to run multiple versions of the same software. But it also has consequences for secure boot.
Lahfa explained that secure boot ""controls who is allowed to run software on your computer"". It relies on using signed binaries; the computer will only boot into the provided kernel if the signature on it is valid. On systemd systems, it is possible to use unified kernel images (UKIs), which package a unified extensible firmware interface (UEFI) boot stub, the kernel, and its initrd together. This has security benefits, because it means that secure boot validates the initrd as well as the kernel. But it causes problems for NixOS, which needs to present many more options in the bootloader than most other distributions in order to support its efficient rollback features.
NixOS's separation of binaries into individual paths under /nix/store — and ability to share libraries between different versions — allows the distribution to keep a large number of previous configurations around. Every time a NixOS system has its configuration changed, from a software update, for example, the complete state of the installed programs is saved as a "generation". In the bootloader, the user can select any previous generation they would like (at least until the old generations are cleaned up to reclaim their storage space), and the kernel will load the appropriate initrd for that generation, which in turn sets up all of the configuration files from that generation. This allows for fearless upgrades, since the previous configuration is available in the boot menu — a value proposition quite similar to image-based distributions. Unfortunately, this ability doesn't work well if the initrd needs to be bundled with the kernel, because that increases both the size of each kernel image, and the number of different kernel images that must be stored. Doing so will quickly fill up the EFI (Extensible Firmware Interface) system partition (ESP).