Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Nix resources

This project is built entirely with Nix. If you are new to Nix — or find the ecosystem confusing — this page is the orientation. It also collects the external resources worth bookmarking.

Nix is not NixOS. Nix is a build tool and package manager that runs on Linux, macOS, and WSL. It builds packages reproducibly and manages dependencies without touching the rest of your system. NixOS is a Linux distribution that uses Nix as its system configuration layer. You do not need NixOS to use Nix, and you do not need NixOS to use this project.


What Nix actually is

Nix is three things layered on top of each other:

  1. A language. A purely functional, lazily evaluated expression language for describing how to build software. Every package is a function from inputs to outputs.
  2. A store. /nix/store/ — an immutable, content-addressed directory where every built output lives at a path derived from a cryptographic hash of everything that went into building it.
  3. A package manager / build system. The nix CLI that evaluates expressions, realises derivations, and manages the store.

Because every output path encodes its full dependency graph, two builds of the same derivation — on any machine — produce the same path and the same bits (given the same inputs). That is the property this project leans on for SLSA L3 attestation.


nixpkgs and NixOS

nixpkgs is the community package repository — a large Nix expression that provides tens of thousands of packages and their build recipes. When a Nix expression says nixpkgs#openssl, it is referring to a package defined in nixpkgs.

NixOS is a Linux distribution that extends nixpkgs with a module system for whole-system configuration — services, users, file systems, and so on. NixOS modules are a nixpkgs concept, not a core-Nix concept. You can use nixpkgs (and therefore all its packages and build helpers) without ever running NixOS.

This project pins a specific revision of nixpkgs via flake.lock so that every build uses the same exact package versions everywhere.


stdenv and build helpers

stdenv is nixpkgs’s standard build environment. It wraps the C toolchain, make, bash, and a set of shell hooks into a baseline that most packages build against. stdenv.mkDerivation is the lowest-level way to define a package build in nixpkgs.

On top of stdenv, nixpkgs provides language-specific build helpers:

HelperWhat it builds
buildGoModuleGo modules, vendoring go.sum
buildRustPackage / craneLibRust crates with cargo
bundlerEnvRuby gem environments
buildPythonPackagePython packages
buildNpmPackageNode / npm projects

This project uses these helpers in pkgs/ to build individual GitLab service binaries, and wraps the results in mkHardenedImage to produce OCI images.


Flakes

A flake is a directory with a flake.nix at the root. It declares:

  • inputs — other flakes or repositories this flake depends on.
  • outputs — the packages, apps, devShells, checks, and NixOS modules this flake provides.

A flake.lock file pins every input to an exact revision and content hash. This makes the whole dependency graph reproducible: anyone who checks out the same commit and runs nix build gets the same store paths.

Flakes replaced the older nix-channel / nix-env workflow. They are now the standard way to manage Nix projects.


Flakes, derivations, and source hashes: how they relate

The chain from a flake input to a built artifact involves three distinct reproducibility anchors.

Flake inputs (nixpkgs, git repos, other flakes) Flake flake.nix declares inputs and outputs flake.lock pins exact revisions + hashes Nix code (expressions and functions) Derivation (.drv) (build recipe and outputs) Derivation inputs (other derivations as build deps) Source + hash (fetched, verified by hash)

Flake inputs (nixpkgs, other flakes, plain git repos) are pinned into flake.lock — exact revisions and content hashes — for reproducibility.

flake.nix (declares inputs and outputs) and flake.lock together make up the flake: a self-contained, reproducible project unit. The flake’s outputs are Nix code: expressions and functions.

Evaluating that code produces a derivation (.drv) — the build recipe describing what inputs are needed and what output path to produce.

A derivation’s inputs split into two kinds:

  • Other derivations — build-time dependencies, chained recursively.
  • Source projects, fetched and hash-verified — via fetchurl, fetchGit, and similar. These are fixed-output derivations where the hash is the trust anchor, not the fetch method.

Hashes anchor trust at both layers: flake.lock pins the source revisions of inputs, and fixed-output derivations pin the content hash of fetched sources. Together they make the full build graph reproducible and auditable.


Learning resources

Official

  • nix.dev tutorials — the recommended starting point. Covers the Nix language, derivations, the store, and flakes with worked examples.
  • NixOS.org: Learn — the official hub for documentation, including the Nix manual, the nixpkgs manual, and NixOS options search.

Community

  • NixOS and Flakes Book — a well-structured community guide focused on the flakes workflow. Covers devShells, NixOS configuration, home-manager, and cross-compilation.

  • Nix Pills — a deep bottom-up walkthrough of how Nix works internally: the store, derivations, stdenv, and how nixpkgs is built up from first principles. Essential reading for understanding why things work the way they do, not just how to use them.

Reference

  • Nix manual — language reference, store semantics, and the nix CLI.
  • nixpkgs manual — stdenv, build helpers, and how to write a derivation for your language.
  • search.nixos.org — search every package in nixpkgs.