Norman's Blog

Nix Pills Notes

Succinct notes from reading https://nixos.org/guides/nix-pills/ and various Nix manual pages.

Nix Store

  • Never change /nix/store manually.

nix-store command

https://nixos.org/manual/nix/stable/command-ref/nix-store.html

  • Manipulates or queries the Nix store

Operation --gc

Operation --realise (-r)

  • Ensures output paths of a derivation are valid

Operation --query (-q)

Querying requisites

To print the closure, i.e. the dependencies, of man (all equivalent commands):

nix-store -qR `which man`
nix-store --query --requisites `which man`
nix-store --query --requisites ~/.nix-profile/bin/man

To show the closure of man in tree form:

nix-store --query --tree `which man`

User Environments

  • A user environment is a /nix/store/<hash>-user-environment folder

Manifest of a User Environment

  • /nix/store/<hash>-user-environment/manifest.nix (symlink) -> /nix/store/hash-env-manifest.nix (file)
  • Current manifest: ~/.nix-profile/manifest.nix

Derivations

A Nix derivation:

  • is stored at /nix/store/<hash>-<name>
  • is identified by its hash
  • can have the same name as another derivation, but with a different hash
  • is ambiguous if specified by its name only
  • has static dependencies, with dependencies hardcoded in them (even hardcoded in binaries)
  • is often interchangeably referred to as a package
  • is created from a Nix expression in a .nix file that is:
    1. Evaluated/Instantiated nix-instantiate, which creates:
    • a derivation file at /nix/store/<hash>-<name>.drv
      • a derivation set
    1. Built/Realised with nix-store --realise (or :b in nix repl)

If a derivation X depends on a derivation Y, then it always depends on it. A version of X which depended on Z would be a different derivation.

Upgrading a library like glibc means recompiling all applications, because the glibc path is hardcoded.

There's no such global path for plugins, so each application must know the specific Nix store path to each plugin.

Attribute paths of a derivation

  • Attribute paths: unambiguous
  • Derivation names: ambiguous

Closure of a derivation

  • Is a list of all a derivation's dependencies, recursively

The builtins.derivation function

The derivation built-in function:

  • receives a set as its first argument
  • returns a derivation set

The first argument set to derivation describes how to build a package, and has at least:

  • "name" attribute
  • "system" attribute
  • "builder" attribute

Calling the derivation function produces a derivation file at /nix/store/<hash>-<name>.drv.

With the derivation function we provide a set of information on how to build a package, and we get back the information about where the package was built.

Nix converts a set to a string when there's an outPath. We refer to other derivations by their outPath.

Derivation Files /nix/store/<hash>-<name>.drv

A .drv derivation file:

  • is a plaintext file
  • can be pretty-printed using nix show-derivation /nix/store/<hash>-<name>.drv

Derivation Sets

A derivation set:

  • is returned by the builtins.derivation function
  • has the attributes:
    • "type" = "derivation"
    • "drvPath" = "/nix/store/-.drv"
    • "outPath" = "/nix/store/<another_hash>-"
      • This attribute behaves like a toString method in other languages.
    • Calling builtins.toString someDerivationSet will evaluate to someDerivationSet.outPath
    • "all":
    • "builder":
    • "drvAttrs":
    • "name":
    • "out":
    • "outputName":
    • "system":

Nix database

  • Is a SQLite database at /nix/var/nix/db that tracks dependencies between derivations.

Nix Profiles

A Nix profile is:

  • a set of derivations (a set of packages)
  • versioned using a a sequence of user environments called generations

$HOME/.nix-profile is:

  • The user's current profile
  • Usually is a symlink to /nix/var/nix/profiles/default

nix profile command

  • nix profile history
  • nix profile list

Nix expressions

Nix expressions:

Nix channels

A Nix channel:

  • is a set of downloadable packages and expressions.
  • is a URL pointing to a place containing Nix expressions.

nix-channel command

  • Manages Nix channels

https://nixos.org/manual/nix/stable/command-ref/nix-channel.html

Common Environment Variables

NIX_PATH

https://nixos.org/manual/nix/stable/command-ref/env-common.html#env-NIX_PATH

~/.nix-defexpr

  • Has several valid file or directory formats. See nix-env --help

nix-env command

  • Manages environments, profiles and their generations

https://nixos.org/manual/nix/stable/command-ref/nix-env.html

Operation --install (-i)

  • nix-env -iA <attribute paths selecting attributes from the top-level Nix expression>
    • Unambiguous, faster, preferred
  • nix-env -i <derivation names of active Nix expression>
    • Possibly ambiguous
  • --dry-run flag
  • By default, all outputs of a derivation are installed.

Operation --upgrade

  • nix-env -u

    • Upgrades everything
    • Specifically, it creates a new user environment, based on the current generation of the active profile, with newer versions of all derivations
  • nix-env -u -A nixpkgs.gcc is an example of upgrading one package

Operation --uninstall

Operation --query (-q)

  • nix-env -q --out-path prints output paths of all derivations of this user's profile's current generation

Nix language

In the Nix language:

  • There are no statements.
  • There are only expressions.
  • Values are immutable.
  • It's all about creating derivations, which are really just sets of attributes to be passed to build scripts.

Strings

Things coerceable to a string:

  • string
  • path
  • derivation (using value of a derivation set's outPath attribute)

You cannot mix strings and integers; you must first do the conversion.

${expr} is called antiquotation

Multiline strings:

nix-repl> "first
          second
          third"
"first\n\second\n\third"

Indented strings:

nix-repl> ''
          a
          b
          ''
"a\nb\n"

Indented strings using '' are common for shell scripts:

stdenv.mkDerivation {
  ...
  postInstall =
    ''
      mkdir $out/bin $out/etc
      cp foo $out/bin
      echo "Hello World" > $out/etc/foo.conf
      ${if enableBar then "cp bar $out/bin" else ""}
    '';
  ...
}

Escaping ${...} in '' is done with '':

nix-repl> ''test ''${foo} test''
"test ${foo} test"

URIs can be written without surrounding ", but is considered an anti-pattern.

Paths

A path must have at least one /.

A path can be specified between angle brackets, e.g. <nixpkgs>.

nix-repl> :t <nixpkgs>
a path

However, <nixpkgs> is not reproducible unless Nixpkgs is pinned.

A path to the current directory:

nix-repl> :t ./.
a path

However, ./. is an anti-pattern because it relies on the name of the folder where the code was built. Use the builtins.path function instead.

A path containing antiquotation:

nix-repl> foo = "x"

nix-repl> :t ./${foo}nix
a path

Lists

Example:

[ 123 ./foo.nix "abc" (f { x = y; }) ]

A list element that is the result of a function call, must be enclosed in round parentheses.

Lists are immutable, like everything else in Nix.

Adding or removing elements from a list is possible, but will return a new list.

Lists are lazy in values and strict in length.

Sets (a.k.a. attribute sets)

Sets are the core of the language.

nix-repl> :t {unquoted="b";        "quoted" = "d"; }
a set

A set is a list of name/value pairs (called attributes) enclosed in curly braces.

Each value is an expression terminated by a semicolon.

Attribute names are strings, and they may be unquoted.

Attribute ordering is irrelevant.

Attribute names may occur only once.

Attributes can be selected from a set using the . operator.

The or keyword provides a default value in an attribute selection.

{ foo = 123; }.${bar} or 456

This will evaluate to 123 if bar evaluates to "foo" when coerced to a string and 456 otherwise (again assuming bar is antiquotable).

Inside a set, you cannot normally refer to elements of the same set:

nix-repl> { a = 3; b = a+4; }
error: undefined variable `a' at (string):1:10

Recursive Sets (a.k.a. Recursive Attribute Sets): rec

nix-repl> rec { a = 3; b = a+4; }
{ a = 3; b = 7; }

In a recursive set, attributes are added to the lexical scope of that same set.

Can cause an infinite recursion error if used improperly.

Using rec is considered an anti-pattern and can be replaced with a let-expression.

Argument Sets

Argument sets are used in functions.

Let-expressions

The let construct adds the variable assignments to the lexical scope of the expression after in:

nix-repl> let a = 3; b = 4; in a + b
7

Two let expressions, one inside the other:

nix-repl> let a = 3; in let b = 4; in a + b
7

Nested let expressions can have shadowed variables:

nix-repl> let a = 3; in let a = 8; in a
8

With-expressions

A with-expression takes a set1 and includes symbols from set1 in the scope of expression expr2:

with set1; expr2

Examples:

nix-repl> longName = { a = 3; b = 4; }
nix-repl> with longName; a + b
7
let blah = { x = "foo"; y = "bar"; }; in
  with blah; x + y

evaluates to "foobar".

The most common use of with is in conjunction with the import function:

with (import ./definitions.nix); ...

makes all attributes defined in definitions.nix available as if they were defined locally in a let-expression.

Inheriting attributes: inherit

let x = 123; in
{ inherit x;
  y = 456;
}

is equivalent to

let x = 123; in
{ "x" = x;
  "y" = 456;
}

and both evaluate to { x = 123; y = 456; }.

--

The following fragment:

inherit x y z;
inherit (src-set) a b c;

is equivalent to the fragment:

x = x; y = y; z = z;
a = src-set.a; b = src-set.b; c = src-set.c;

when used while defining local variables in a let-expression or while defining a set.

Functions

Conditionals

if e1 then e2 else e3

where e1 is an expression that should evaluate to a Boolean value (true or false).

with expressions

Operators

The set1 // set2 operator is considered an anti-pattern because a nested set in set1 is replaced by a nested set in set2, not merged together. Use the pkgs.lib.recursiveUpdate function instead.

nix-build command

Builds a Nix store derivation from a Nix expression.

https://nixos.org/manual/nix/stable/command-ref/nix-build.html

Runs:

  1. nix-instantiate to translate a high-level Nix expression to a low-level store derivation
  2. nix-store --realise to build the store derivation

Common Command Options

https://nixos.org/manual/nix/stable/command-ref/opt-common.html