nixpkgs-basics.md

Meet nixpkgs

Before this, you'll want

  1. Named function inputs
The Nix language10 min

Meet the nixpkgs repository

Sooner or later, every answer you find to a Nix question ends the same way: it’s in nixpkgs. Nobody ever stops to say what that actually is, and the first time you go and look for yourself, you find a repository with a few hundred thousand files in it and quietly close the tab.

So let’s open it together, because you only ever need to care about three of those folders.

Nixpkgs course snapshot is where the community describes packages such as Git, Firefox, Vim, and thousands of others. Open the folders below and have a look around. Open a Nix file and you’ll see what its job is, without facing a wall of real implementation code.

NixOS / nixpkgs
nixpkgs/
pkgs/package recipes
by-name/packages grouped by name
gi/
git/
󱄅package.nix

The recipe for building Git.

vi/
vim/
󱄅package.nix

The recipe for building Vim.

applications/older package layout

More application recipes live here, from before by-name existed.

top-level/assembles the package set
󱄅all-packages.nix

Connects package recipes to the attributes you type in pkgs.

lib/reusable Nix functions
󱄅lists.nix

Functions for working with lists.

󱄅strings.nix

Functions for working with strings.

󱄅modules.nix

The machinery behind the module system.

󱄅default.nix

Collects the library functions into lib.

nixos/NixOS modules and tests
modules/
programs/

Options for programs such as Git and Firefox.

services/

Options for services such as SSH and nginx.

system/

The modules that assemble the operating system.

tests/

Tests that boot virtual NixOS machines.

󱄅default.nix

The entry point for NixOS evaluation.

maintainers/people caring for packages
󱄅maintainer-list.nix

The people and teams who look after packages.

doc/project documentation

Manuals and contributor documentation.

󱄅default.nix

The classic entry point that evaluates nixpkgs.

󱄅flake.nix

The modern flake outputs the repository provides.

pkgs/ contains package recipes

So what is actually inside pkgs/? Not Firefox, and not Git (at least not their binaries)

What it stores instead is Nix expressions, one per package, each explaining where to fetch the source code and how to build it. A recipe rather than a meal.

Each recipe tells the Nix builder what to do, and the finished package ends up in the Nix store.

Those recipes become pkgs

Recipes sitting in folders are not something you can reach for from a configuration, though. So how do a few hundred thousand files turn into something you can actually use?

When nixpkgs goes through evaluation, every one of those recipes gets collected into a single enormous attribute set, and that set is what everybody means when they say pkgs:

Try it

Reach for Firefox instead of Git.

nix replevaluated as you typeNixA plain Nix expression. Nothing from nixpkgs or a module system is supplied.

Which means pkgs.git is nothing more exotic than selecting an attribute out of a set, exactly the way you already know how to. You get a tidy name instead of hunting through repository folders.

Nixpkgs contains more than packages

And packages are not all that lives in there.

The lib/ directory provides reusable Nix functions. The nixos/ directory contains the modules and option definitions used to build NixOS systems.

So one repository quietly supplies three things you will keep meeting:

  • packages through pkgs
  • helper functions through lib
  • NixOS modules and options

Nixpkgs never stops moving

Here is the part that catches people out. Nixpkgs never stops moving, and two snapshots taken a week apart can differ in package versions, recipes and NixOS options.

Which means “I used nixpkgs” promises nothing. Your friend used nixpkgs too, and got a different Firefox, a different Git, and an option you don’t have.

So to reproduce a build you eventually need to know which revision of nixpkgs supplied pkgs. The command line can resolve a current snapshot for you, which is all you want for a quick experiment. A project lockfile can pin one exact revision, which is what you want the moment somebody else has to build the same thing. You will use both.

PickA colleague says "it builds fine for me, I used nixpkgs too". What has that told you?

Real code is usually handed pkgs

The good news is that most of the time you don’t fetch any of this yourself. Inside a NixOS module, NixOS hands you pkgs as a function input, and you simply use it:

configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

Where that pkgs came from is decided one level up. Flakes select a package set from a pinned nixpkgs input, which is the path this course builds toward.

Older code and older guides do it differently: they use a channel and write import <nixpkgs> { }. That spelling is everywhere, so you should be able to read it when you meet it. It is just not the one to build your own setup on.

Know which layer to inspect

The repository is enormous, but you now know its three doors. The skill worth having from here is walking through the right one on the first try.

PickYou want to read every setting NixOS accepts for OpenSSH, from the source rather than from a search engine. Which folder declares them?

So what you are after tells you which door to open. A program’s build recipe is under pkgs/. A function for transforming values is under lib/. And a system setting, along with the documentation printed beside it, is under nixos/.

What to keep

  • Nixpkgs is one enormous repository of Nix code, and pkgs is what it evaluates to.
  • It holds more than packages: the NixOS modules and lib live there too.
  • Nixpkgs moves, so reproducing a build needs a particular revision rather than only the repository’s name.
  • Inside a module you are normally handed pkgs as a named function input.
  • Channels and <nixpkgs> are worth being able to read, because older guides are full of them. Lockfiles are what this course builds toward.

Useful links

NORMALCOURSE IN BETA