The Nix Store
Write this to completion.
Nix is purely functional but in the context of file system (as opposed to values stored in memory). As such, how this file system is structured (called the Nix Store) is the first foundational concept to understand.
The Nix store is located in the /nix/store
directory by default. The contents of this directory are called store paths. For eg., /nix/store/05p0my9hlc33iamk3rzg61rgg1fhrf7w-haskell-template-0.1.0.0
is a store path. Thus a Nix store is simply a collection of store paths. The nix build process largely involves transformation of these store paths to produce further new store paths.
- File system diagram of Nix store
- Entities connected to one another.
Kitchen analogy
Let's try a real-world analogy to understand the Nix store.
If the Nix store is the kitchen, then the store paths are the various objects in it -- foodstuff, ingredients, recipe booklets, cooked food, dinner servings, etc.
Let's say you want to cook a cheeseburger. In Nix-speak, we say that we want to build the cheeseburger package. To cook (build) the cheeseburger, however, we need a receipe first. In Nix-speak, we call this recipe a derivation. Both packages and derivations are store paths that exist in the Nix store; the Nix store uniformly treats them as store paths, with no special treatment. Likewise, both the cheeseburger recipe (as a paper document) and the cheeseburger itself (as a cooked food) exist in your kitchen as physical objects.
A tabular comparison of the terms, establishing nomenclature for rest of article.
...
- Kitchen recipes
- Sharing recipes with neighbours
Interactive exploration
TODO: nix commands to explore/manipulate the store directly
nix store add-file
nix store add-path
nix store delete
nix store prefetch-file
Creating a recipe (derivation)
There is a nix derivation add
command to create a derivation via JSON, but let's use the Nix language to do this, in the REPL (using the bulitin function derivation
), as it is more convenient.
$ nix repl
nix-repl> drv = derivation {
name = "hello";
builder = "/bin/bash";
system = "aarch64-darwin";
args = [ "-c" "echo Hello > $out"];
}
nix-repl> drv
«derivation /nix/store/2dc96vagivg3h45sbkr2jrl31xnmdj2c-hello.drv»
nix-repl> :b drv
This derivation produced the following outputs:
out -> /nix/store/gaarvnj99dcfx8c8wnvfsqzql2fj5d65-hello
Here /nix/store/2dc96vagivg3h45sbkr2jrl31xnmdj2c-hello.drv
is the derivation (or "recipe"). Building (or "cooking") it gives us the package (or "cooked food") /nix/store/gaarvnj99dcfx8c8wnvfsqzql2fj5d65-hello
. Note that both the derivation and the package are just store paths. The recipe itself does nothing fancy, aside from creating a file with the contents "Hello" in it. In Nix of course it is possible to create derivations that build an entire Linux distribution (NixOS), just as one might gather up a set of recipes to cook for a big party resulting in a big feast (the final "package").
A derivation can use outputs of another derivation, just as a recipe can use the product of another recipe:
# Uses the derivation defined above, by referencing `${drv}` that points to the
# out path of that derivation
nix-repl> :b derivation {
name = "hello-world";
builder = "/bin/bash";
system = "aarch64-darwin";
args = [ "-c" "/bin/cat ${drv} > $out; echo World >> $out"];
}
This derivation produced the following outputs:
out -> /nix/store/nw7fyal65xfzbhaqxjgfm9i4m4fyd92l-hello-world
There are more convenient ways to write derivations, such as stdenv.mkDerivation
. We'll expore these in the Nix language section.
Exercises
TODO