Why Nix?
FHS paths like /bin/python tell you nothing. You don’t
know the patch release, the linked dynamic libraries, or what build
flags were set on the host.
Docker wraps that mystery in a tarball and calls it isolation. But
putting an impure build inside a container doesn’t make it reproducible;
it just makes it portable. If two machines run docker build
on the same Dockerfile, ambient network fetches and host tools mean they
can still produce different binaries.
Nix replaces ambient filesystem paths with content-addressed store
paths:
/nix/store/<hash>-<name>-<version>.
Before anything builds, Nix evaluates the package into a derivation:
- An exact list of all files and compiler dependencies needed
- Explicit environment variables and build flags
- The exact hash of the source code
- The isolated sandbox parameters
Example derivation output
For example, here are the outputs of the GNU Hello package (some fields have been omitted for brevity):
{
"/nix/store/sg3sw1zdddfkl3hk639asml56xsxw8pf-hello-2.10.drv": {
"outputs": {
"out": {
"path": "/nix/store/dvv4irwgdm8lpbhdkqghvmjmjknrikh4-hello-2.10"
}
},
"inputSrcs": ["/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],
"inputDrvs": {
"/nix/store/8pq31sp946581sbh2m18pb8iwp0bwxj6-stdenv-linux.drv": ["out"],
"/nix/store/cni8m2cjshnc8fbanwrxagan6f8lxjf6-hello-2.10.tar.gz.drv": ["out"],
"/nix/store/md39vwk6mmi64f6z6z9cnnjksvv6xkf3-bash-4.4-p23.drv": ["out"]
},
"platform": "x86_64-linux",
"builder": "/nix/store/kgp3vq8l9yb8mzghbw83kyr3f26yqvsz-bash-4.4-p23/bin/bash",
"args": ["-e", "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],
"env": {
"buildInputs": "",
"builder": "/nix/store/kgp3vq8l9yb8mzghbw83kyr3f26yqvsz-bash-4.4-p23/bin/bash",
"doCheck": "1",
"name": "hello-2.10",
"nativeBuildInputs": "",
"out": "/nix/store/dvv4irwgdm8lpbhdkqghvmjmjknrikh4-hello-2.10",
"outputs": "out",
"pname": "hello",
"src": "/nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz",
"stdenv": "/nix/store/hn7xq448b49d40zq0xs6lq538qvldls1-stdenv-linux",
"system": "x86_64-linux",
"version": "2.10"
}
}
}Nix realizes the derivation inside an isolated sandbox with no network access and no ambient environment leakage. The same declared inputs produce the exact same bit-for-bit outputs.
The consequences:
- Reproducibility: Builds do not rot. A derivation evaluated today builds identically five years from now.
- Trivial Caching: If the inputs haven’t changed, reuse the output hash. No redundant compilations.
- Coexisting Versions: Multiple versions of the same library run side-by-side without path collisions.
- Atomic Rollbacks: State transitions are symlink swaps, not in-place mutations.