Nix Notes
Hi, I've been using nix and nixos for a while now and I decided to write down some of the thoughts that I would have liked to have been able to read when I started learning nix. I doubt this will be a very good or popular tutorial, but there really aren't many good resources on nix that I've found at all, so contributing anything seems potentially helpful.
The hardest part for me when learning nix was that the required prerequisite knowledge was never clear when trying to learn some new area. So In this post I'll attempt to lay out a broad strokes organization of nix's many components and their interdependencies.
This is extremely incomplete, but possibly helpful to someone!
Good external resources
There are a few good external resources I'd be remiss to not at least mention here:
- The official website
- Nixpkgs Search (A page for searching Nix & NixOS packages)
- The official Nix wiki
- The Nix Reference Manual
- Zero to Nix
- NixOS and flakes
- Practical flake anatomy (A good introduction to flakes)
Lingo
First lets talk some common words used in nix, to create some clarification going into this.
- The Nix project contains many parts, which are listed below, but generally provide a declaritive and reproducable way of building (parts of) computer systems.
- The Nix language is a pure, functional programming language, but for nix it effectively serves as a very fancy configuration format, like JSON, YAML, TOML, or XML. It is used widely throughout the system most notibly for configuring (and creating) nix derivations, in the nix package manager, and in nixos in modules (all of which discussed below).
- The Nix package manager builds packages, installs, and configures packages (e.g. applications or data as part). All packages are built in a reproducable way, meaning that every time the same version of the package is built, the output files will be the same.
- Nixpkgs is the name of the main central repository that contains software packaged for nix. The source for all package derivations are available on github and packages can be searched here.
- The Nix Store is the location on the filesystem where packages are built (or downloaded) to. Nix packages in the store are not considered "installed," and packages will not be deleted automatically. Additionally, once placed there, all packages will not be modified by the package manager, updates are installed in a separate folder. (To manually remove old packages, run
nix gc) - Derivations are a generic type within the Nix language that represents anything that can be built by the nix package manager into some output files. Derivations can represent packages, system configurations, containers, or even dev shells. More precisely, derivations represent a set of operations (typically in the form of bash commands) performed on a specified input (set of files) to produce an output (set of) folder(s).
- NixOS is an entire OS built using the nix package manager with the Nix language being used for system configuration (see nix modules below), and the entire system configuration being a large derivation.
- A nixos module is a component of nixos that represents the configuration needed to run a specific piece of software, such as an SSH server, graphical interface, or the linux kernel itself. They can be composed in a heirarchy to form a complex system configuration and nixpkgs includes thousands of them
- A channel is a system-wide configuration that controlls which version of nixpkgs refer to. Even though every version of a package is reproducible and immutable, nixpkgs updates with time as new software releases come out, so some packages get held back according to a bi-yearly release schedule. This system isn't the best because of the lack of reproducibility and Flakes (below) replaces it.
- A Flake is a configuration structure that builds itself arround a derivation, adding the capability to version-lock inputs. Fundamentally a flake configuration file contains the following: a list of inputs, and a list of outputs. Each output can be of different types including packages, dev shells, or even entire system configurations! Outputs are additionally separated by hardware architechure and target platform (e.g. x86 and linux or arm and macos). Flakes also have a "lock file," which contains a machine-readable specific/exact versions for all inputs listed in the flake's config. Flakes also are aware of and use Git for version control.
Woah, that's a lot, but hopefully that gives a good baseline for what the heck a lot of these things are talking about.
The Nix Language
Next I want to delve a bit deeper into the nix language itself, and show some examples of how to use it and exactly what it does. To do this, I'll be comparing it with JSON for now, so I'll be assuming you have some knowledge of what that is and what it's used for.