pix¶
Explore Nix internals through readable Python.
Nix's core algorithms — store path hashing, NAR serialization, derivation parsing, the daemon wire protocol — are buried in C++ across dozens of source files. pix re-derives each one in straightforward Python so you can read, modify, and single-step through the logic.
Every module produces output identical to the real nix CLI, verified by the test suite. The code is the documentation; these pages are the commentary.
What's inside Nix¶
When you run nix build, a lot happens under the hood. pix breaks it into pieces you can understand one at a time:
| Concept | What Nix does | pix module | Docs |
|---|---|---|---|
| Base32 | Custom encoding for store path hashes — not RFC 4648 | base32.py |
How it differs |
| Hash compression | XOR-folds SHA-256 (32 B) down to 160 bits (20 B) | hash.py |
In store path computation |
| NAR | Deterministic archive format — no timestamps, no uid, just content | nar.py |
Wire format spec |
| Store paths | /nix/store/<hash>-<name> computed from a fingerprint string |
store_path.py |
Full algorithm |
| Derivations | .drv files in ATerm format; hashDerivationModulo breaks circular deps |
derivation.py |
Format + hashing |
| Daemon protocol | Unix socket with uint64-LE framing, stderr log stream, operation opcodes | daemon.py |
Protocol spec |
pixpkgs — building on pix¶
Once you understand the internals, pixpkgs shows how to build a nixpkgs-like package set on top of them, mapping Nix patterns to Python idioms:
| Nix pattern | Python idiom | pixpkgs module |
|---|---|---|
mkDerivation |
drv() function → Package dataclass |
drv.py |
callPackage |
inspect.signature + getattr |
package_set.py |
String interpolation (${pkg}) |
__str__ returning output path |
drv.py |
pkg.override |
Re-call drv() with merged kwargs |
drv.py |
nix-store --realize |
realize() → daemon add_text_to_store + build_paths |
realize.py |
See the pixpkgs API reference for details.
Overlays and the bootstrap¶
The deepest rabbit hole in Nix: how does nixpkgs build GCC when building GCC requires GCC? The answer is overlays composed via a fixed-point — and it maps surprisingly well to Python's self and method override. We explore four different Python implementations, each revealing different failure modes:
| Experiment | Pattern | final |
prev |
|---|---|---|---|
| A | Class inheritance | self (MRO) |
self._prev (manual) |
| B | __getattr__ chain |
_final ref |
_prev link |
| C | Lazy fixed-point | LazyAttrSet proxy |
prev dict |
| D | Class decorator | self (MRO) |
self._prev (auto) |
The full analysis — including an infinite recursion trap in class inheritance, the real nixpkgs 7-stage bootstrap, and a comparison of tradeoffs — is in Overlays & Bootstrap.
Reading order¶
The modules build on each other. Start from the bottom:
pix (Nix internals):
1. base32.py ← simplest: just an encoding
2. hash.py ← one function: XOR-fold
3. nar.py ← serialization format, uses hash
4. store_path.py ← the core algorithm, uses base32 + hash
5. derivation.py ← parsing + the hashDerivationModulo trick
6. daemon.py ← standalone: wire protocol over Unix socket
pixpkgs (package set layer, uses pix):
7. drv.py ← drv() + Package: the mkDerivation equivalent
8. package_set.py ← PackageSet.call(): the callPackage equivalent
9. realize.py ← write .drv to store + build via daemon
Each pix file is self-contained and under 150 lines. You can read the entire codebase in one sitting.
Try it yourself¶
nix develop
# See that pix computes the exact same hash as nix
python -m pix hash-path ./pix/base32.py --base32
nix hash path ./pix/base32.py --type sha256 --base32
# same output
# Compute a store path, then verify via the daemon
python -m pix store-path ./pix --name pix-source
python -m pix add-text hello.txt "hello world"
python -m pix drv-show /nix/store/...-hello.drv
Verify¶
How to use these docs¶
- Internals — Start here. Explains how Nix works with diagrams, hex dumps, and protocol traces.
- API Reference — Function signatures and usage examples for each module.
- CLI Reference — The
python -m pixcommands for quick experimentation.