Skip to content

Latest commit

 

History

History
217 lines (146 loc) · 4.69 KB

30-fundamentals.org

File metadata and controls

217 lines (146 loc) · 4.69 KB

How does Nix do it?

Implementation details


  • Declarative
  • Reproducible
  • Functional
  • Pure
  • Lazy

Declarative vs Imperative


Tell the computer what to do,

users.spacekookie.homeDir = "/home";

not how to do it

# useradd spacekookie -d /home

Declarative onion


This system works in layers!

  1. Your configuration sets a value (users.spacekookie.homeDir = "/home";)
  2. users module provides options, and evaluates settings
  3. Impure layer: (e.g.) run useradd ..., conditionally based on whether that user already exists in passwd file, etc

Reproducible


  • Nix configuration changes are idempotent
    users.spacekookie = {
      createHome = true;
      homeDir = "/home";
      extraGroups = [ "wheel" "dialout" ];
    };
        

Reproducible


  • The same build inputs yield the same build outputs
    • Build inputs are hashed, and can be re-used if already present
  • If build inputs may change, build sare fixed by their output hash (more on that later)

Reproducible


build-01-set = [ 9gkyl3knyalavd5v77rb0ciwry1r4v77-foo
                 gm1vihrf3d8hks2fgjfgfyn5wm2rs49a-bar ]

build-02-set = [ 9gkyl3knyalavd5v77rb0ciwry1r4v77-foo
                 psfi2l3kqpsp2zv66ngnaqhxnbzx1dn7-bar ]

Because the hash of the foo input is the same, it can be re-used from the store. The bar package was updated, and thus needs to be rebuilt!

Tangent: the nix store


  • Usually located at /nix/store
  • Special permission setup
    • Owned by root:nixbld
    • Write permission on /nix/store for owner and group
    • No write permissions for actual outputs (e.g. /nix/store/<hash>-foo/)
    • Additional t bit on /nix/store, which means that removing a file requires write-permission on the file, not just the containing directory.

Tangent: the nix store


$ /n/s/zzg015adjliwmdm4jfkbhnkpw6dmq1ym-urxvt-autocomplete-all-the-things-1.6.0> tree -p                                                                                   
.
└── [dr-xr-xr-x]  lib
    └── [dr-xr-xr-x]  urxvt
        └── [dr-xr-xr-x]  perl
            └── [-r-xr-xr-x]  autocomplete-ALL-the-things

3 directories, 1 file

The result of all this?

A nixbld user can create a new directory and store build outputs, but never remove or change them again! Build artifacts are read-only!

Pure


  • Functions have no side-effects
  • Inputs map directly to outputs
let
  makeYouUnderstand = rickAstley {
    giveYouUp = "never";  letYouDown = "never";
    runAround = "never";  desertYou = "never";
    makeyouCry = "never"; sayGoodbye = "never";
    tellALie = "never"; hurtYou = "never";
  };
in
{ }

Functional


(no it doesn’t mean “it works”)

  • Functions are first-class types in the Nix language
  • Functions can be…
    • passed as parameters
    • returned as results

Syntax is Haskell inspired:

let cube = x: y: z: x * y * z;
in
(cube 2 4 8)

Lazy


Expressions are only evaluated when they are needed for the result of an operation.

{
  never = abort "<oh-no.jpg>";
  use = "I'm a String";
}.use

Why?!


As in: why go through all this trouble

Unique names for every package


  • Dependency closures solve a lot of problems
  • Closures only work in a pure environment
  • Pure environments demand certain design principles (functional, lazy, reproducible)

Closures


We’ll get into the specifics but there are two scenarios that closures can cover.

Two rules if you will…

Rule #1


I’m building some software, and I don’t know the exact hash of what I will be producing!


  • You can do arbitrary computation
  • Produce arbitrary outputs
  • The build can not access the network!

Rule #2


I’m fetching a source archive. I know exactly what I will produce, so give me network access!


  • Only run once: will not be built again after the source is fetched
  • Arbitrary computation is still possible, but bulider can not produce arbitrary outputs
  • The exact hash of this build must be known ahead of time