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)
- So you can’t just assume something will be in
- 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
- which parts of the infinite
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