Nix fireside chat outline

This is simply an outline, with no actual content.

The source of truth remains Eelco Dolstra’s thesis.

Why Nix

  • “Works on my machine”
  • Rollbacks and deletion
  • Multiple simultaneous installations of things
  • Deduplicate precisely what can be deduplicated

Basic ideas

  • Every package describes its build- and run-time dependencies precisely
  • Cryptographic hashing to identify dependencies
    • A package is identified by a hash which encompasses itself and all its dependencies
    • Can find uses of a dependencies by dumb search for hash strings! This… actually works in practice (empirically)!
    • Lots of rewriting of e.g. hashbangs, library loads, etc
      • Can dynamically link, but you must know at build time precisely what you’ll be dynamically linking
  • Atomic changes
  • The Nix store holds every package
    • So you can’t just assume something will be in /usr/bin
    • Dynamic linker is intentionally crippled
    • Notionally read-only and contains the entire world (garbage-collector required)
  • Reproducible builds
    • Can cache build results centrally and then download them, rather than rebuilding from source
    • Upcoming feature: content-addressed Nix store

NixOS (and Guix)

  • Key insight: an operating system is just another package
    • Kernel
    • Bootloader
    • Systemd jobs
    • Shell
  • All symlinks into the Nix store
  • Benefits:
    • Trivial rollback
    • Can create the new version during normal operation, and then atomically switch to it by flipping a symlink when it’s ready
      • (asterisk: systemd restarts etc)
      • Same for user environments: $PATH is set to a single symlink, and then the target of that symlink is atomically changed for each update
  • Very unlike most other Linuxes!

How a Nix installation works

  • Daemon controls the store, you ask it to build stuff
  • /nix/store is notionally infinite but you can only store finite chunks of it
  • Database stores:
    • which parts of the infinite /nix/store are known to be correctly instantiated locally
    • cache of reference graphs
    • mapping of “which derivation caused each path to be reified on disk”
    • content hashes, to detect tampering

How a package is built

  • Write a Nix expression describing the package
  • Instantiate that expression into a store derivation, and put in store
    • Low-level build instructions for the package
  • Realise (build) that derivation into the store
    • Download any build artefacts (sources, compilers)
    • Build e.g. any compilers recursively if necessary, and put in store
    • Put sources directly into store
    • Execute the package’s builder with the inputs that now exist
    • Place result in store

Flakes (if we have time)