What does the hash in a Nix store path actually name? — LabCraft BlogStart your first lab →
BlogManifestoContactStart your first lab →
A Nix store path looks like this:
text<br>/nix/store/s0psayl7zvkvwdcqc8fy1sbv8rlf1yq8-bash-5.3p9
The last bit is friendly. This one contains Bash 5.3p9. The 32 characters before<br>it are harder to explain.
“The hash comes from the inputs” is a common answer. It is also incomplete. Is<br>Nix hashing the file you wrote, the build recipe it evaluates to, the bytes<br>produced by the build, or the packages it depends on?
There is not one naming rule behind every store path.
Most package paths are named from the recipe
For a normal package build, the .nix file is a description. Nix evaluates that<br>description into a derivation, which is the concrete build recipe. The recipe<br>names the builder, arguments, environment, declared outputs, and dependencies<br>that Nix will use.
That gives Nix enough information to determine an input-addressed output path<br>before the build runs. The finished bytes do not need to exist yet.
This is why editing a Nix expression does not always produce a new path. Two<br>expressions can evaluate to the same recipe. It is also why an edit that changes<br>an actual recipe input produces a different identity. Nix names what it will<br>build, not the spelling of the expression that described it.
Some paths are named from their contents
Nix can also name a store object from bytes it already has. nix store add is a<br>simple example. Here the content exists first, so Nix can hash it directly. The<br>path is content-addressed.
Both kinds of path live under /nix/store. Calling every store path<br>“content-addressed” misses the distinction. For one, the build plan determines<br>the identity before an output exists. For the other, the content supplies the<br>identity.
That distinction makes several bits of Nix behavior less mysterious. It helps<br>you predict whether a change should move a path, understand why an old result<br>can remain beside a new one, and reason about what a cache can safely reuse.
The name is only part of the record
A store path rarely works alone. Built paths contain references to other store<br>paths, and Nix records those references as a graph. Follow the graph from one<br>path and you get its closure: everything that must travel with it to another<br>machine.
The same record lets Nix explain why a dependency is present and check whether<br>the bytes on disk still match what it recorded. Store paths are not opaque<br>directory names. They are identities inside a database Nix can query.
Why this became Part 2
First Contact was deliberately about a new learner's first session with Nix:<br>install it, see the store, use packages without adding them to the host, declare<br>a script's dependencies, and remove the installation cleanly.
Store Paths goes underneath that command-line introduction. It runs on a<br>real NixOS machine because the operating system itself is the largest store<br>object a learner can inspect. It does not require the Nix language. The example<br>expressions are staged so the learner can focus on reading what Nix produced.
The five labs put four questions in front of the learner:
What on the running system resolves into /nix/store?
Which changes affect recipe identity?
When is a path named from a recipe, and when is it named from bytes?
How do references, closures, and integrity fit into the same model?
Start the Nix course. See what you predict before the machine gives<br>you the answer.
Share this
Read next<br>Engineering · Nix · Reproducibilitynix Didn't Hang. It Was Evaluating the World!
Announcement · Nix · NixOSLearn Nix on a real Linux VM: LabCraft is open in public beta
Start your first lab.<br>LabCraft is open as a public beta. GitHub, Google, or a magic link to your inbox — pick your way in.
GitHubGoogle<br>Email link →<br>By continuing, you confirm that you are at least 18, agree to our Terms, and acknowledge our Privacy Policy.
LabCraft · Beta · 2026PrivacyTerms<br>labcraft.dev