nix Documentation

Nix, the purely functional package manager

RAW Doc

Technical Documentation: NixOS/nix

ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference

Overview (`README.md`)

Nix


Nix is a powerful package manager for Linux and other Unix systems that makes package
management reliable and reproducible. Please refer to the Nix manual
for more details.

Installation and first steps

Visit nix.dev for installation instructions and beginner tutorials.

Full reference documentation can be found in the Nix manual.

Building and developing

Follow instructions in the Nix reference manual to set up a development environment and build Nix from source.

Contributing

Check the contributing guide if you want to get involved with developing Nix.

Additional resources

Nix was created by Eelco Dolstra and developed as the subject of his PhD thesis The Purely Functional Software Deployment Model, published 2006.
Today, a world-wide developer community contributes to Nix and the ecosystem that has grown around it.

License

Nix is released under the LGPL v2.1.


Overview (`maintainers/README.md`)

Nix maintainers team

Motivation

The team's main responsibility is to guide and direct the development of Nix and ensure that the code is in good shape.

We aim to achieve this by improving the contributor experience and attracting more maintainers – that is, by helping other people contributing to Nix and eventually taking responsibility – in order to scale the development process to match users' needs.

Objectives

  • It is obvious what is worthwhile to work on.
  • It is easy to find the right place in the code to make a change.
  • It is clear what is expected of a pull request.
  • It is predictable how to get a change merged and released.

Tasks

  • Establish, communicate, and maintain a technical roadmap
  • Improve documentation targeted at contributors
    • Record architecture and design decisions
    • Elaborate contribution guides and abide to them
    • Define and assert quality criteria for contributions
  • Maintain the issue tracker and triage pull requests
  • Help contributors succeed with pull requests that address roadmap milestones
  • Manage the release lifecycle
  • Regularly publish reports on work done
  • Engage with third parties in the interest of the project
  • Ensure the required maintainer capacity for all of the above

Members

See https://nixos.org/community/teams/nix/ for the current team membership.

The team is on Github as @NixOS/nix-team.

Meeting protocol

The team meets twice a week (times are denoted in the Europe/Amsterdam time zone):

  • Discussion meeting: Wednesday 21:00-22:00 Europe/Amsterdam see calendar.

    1. Triage issues and pull requests from the No Status column (30 min)
    2. Discuss issues and pull requests from the To discuss column (30 min).
      Once a month, each team member checks the Assigned column for prs/issues assigned to them, to either
      • unblock it by providing input
      • mark it as draft if it is blocked on the contributor
      • escalate it back to the team by moving it to To discuss, and leaving a comment as to why the issue needs to be discussed again.
  • Work meeting: Mondays 18:00-20:00 Europe/Amsterdam; see calendar.

    1. Code review on pull requests from In review.
    2. Other chores and tasks.

Meeting notes are collected on a collaborative scratchpad.
Notes on issues and pull requests are posted as comments and linked from the meeting notes, so they are can be found from both places.
All meeting notes are published on Discourse under the Nix category.

Team meetings are generally open to anyone interested.
We can make exceptions to discuss sensitive issues, such as security incidents or people matters.
Contact any team member to get a calendar invite for reminders and updates.

[!IMPORTANT]
Handling security reports always takes priority.

Project board protocol

The team uses a GitHub project board for tracking its work.

Items on the board progress through the following states:

No Status

During the discussion meeting, the team triages new items.
To be considered, issues and pull requests must have a high-level description to provide the whole team with the necessary context at a glance.

On every meeting, at least one item from each of the following categories is inspected:

  1. critical
  2. security
  3. regression
  4. bug
  5. tests of existing functionality

Team members can also add pull requests or issues they would like the whole team to consider.
To ensure process quality and reliability, all non-trivial pull requests must be triaged before merging.

If there is disagreement on the general idea behind an issue or pull request, it is moved to To discuss.
Otherwise, the issue or pull request in questions get the label idea approved.
For issues this means that an implementation is welcome and will be prioritised for review.
For pull requests this means that:

  • Unfinished work is encouraged to be continued.
  • A reviewer is assigned to take responsibility for getting the pull request merged.
    The item is moved to the Assigned column.
  • If needed, the team can decide to do a collarorative review.
    Then the item is moved to the In review column, and review session is scheduled.

What constitutes a trivial pull request is up to maintainers' judgement.

To discuss

Pull requests and issues that are deemed important and controversial are discussed by the team during discussion meetings.

This may be where the merit of the change itself or the implementation strategy is contested by a team member.
Whenever the discussion opens up questions about the process or this team's goals, this may indicate that the change is too large in scope.
In that case it is taken off the board to be reconsidered by the author or broken down into smaller pieces that are less far-reaching and can be reviewed independently.

As a general guideline, the order of items to discuss is determined as follows:

  • Prioritise pull requests over issues

    Contributors who took the time to implement concrete change proposals should not wait indefinitely.

  • Prioritise fixing bugs and testing over documentation, improvements or new features

    The team values stability and accessibility higher than raw functionality.

  • Interleave issues and PRs

    This way issues without attempts at a solution get a chance to get addressed.

In review

Pull requests in this column are reviewed together during work meetings.
This is both for spreading implementation knowledge and for establishing common values in code reviews.

When the overall direction is agreed upon, even when further changes are required, the pull request is assigned to one team member.
If significant changes are requested or reviewers cannot come to a conclusion in reasonable time, the pull request is marked as draft.

Assigned

One team member is assigned to each of these pull requests.
They will communicate with the authors, and make the final approval once all remaining issues are addressed.

If more substantive issues arise, the assignee can move the pull request back to To discuss or In review to involve the team again.

Flowchart

The process is illustrated in the following diagram:

mermaid
flowchart TD
    discuss[To discuss]

    review[To review]

    New --> |Disagreement on idea| discuss
    New & discuss --> |Consensus on idea| review

    review --> |Consensus on implementation| Assigned

    Assigned --> |Implementation issues arise| review
    Assigned --> |Remaining issues fixed| Merged

Overview (`maintainers/keys/README.md`)

Maintainer GPG Keys

Release tags are signed by members of the Nix maintainer team as part of the release process. This directory contains the public GPG keys used for signing.

Keys


Overview (`src/external-api-docs/README.md`)

Getting started

Warning These bindings are experimental, which means they can change
at any time or be removed outright; nevertheless the plan is to provide a
stable external C API to the Nix language and the Nix store.

The language library allows evaluating Nix expressions and interacting with Nix
language values. The Nix store API is still rudimentary, and only allows
initialising and connecting to a store for the Nix language evaluator to
interact with.

Currently there are two ways to interface with the Nix language evaluator
programmatically:

  1. Embedding the evaluator
  2. Writing language plug-ins

Embedding means you link the Nix C API libraries in your program and use them from
there. Adding a plug-in means you make a library that gets loaded by the Nix
language evaluator, specified through a configuration option.

Many of the components and mechanisms involved are not yet documented, therefore
please refer to the Nix source code for
details. Additions to in-code documentation and the reference manual are highly
appreciated.

The following examples, for simplicity, don't include error handling. See the
[Handling errors](@ref errors) section for more information.

Embedding the Nix Evaluator{#nix_evaluator_example}

In this example we programmatically start the Nix language evaluator with a
dummy store (that has no store paths and cannot be written to), and evaluate the
Nix expression builtins.nixVersion.

main.c:

c
#include <nix_api_util.h>
#include <nix_api_expr.h>
#include <nix_api_value.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// NOTE: This example lacks all error handling. Production code must check for
// errors, as some return values will be undefined.

void my_get_string_cb(const char * start, unsigned int n, void * user_data)
{
    *((char **) user_data) = strdup(start);
}

int main()
{
    nix_libexpr_init(NULL);

    Store * store = nix_store_open(NULL, "dummy://", NULL);
    EvalState * state = nix_state_create(NULL, NULL, store); // empty search path (NIX_PATH)
    Value * value = nix_alloc_value(NULL, state);

    nix_expr_eval_from_string(NULL, state, "builtins.nixVersion", ".", value);
    nix_value_force(NULL, state, value);

    char * version;
    nix_get_string(NULL, value, my_get_string_cb, &version);
    printf("Nix version: %s\n", version);

    free(version);
    nix_gc_decref(NULL, value);
    nix_state_free(state);
    nix_store_free(store);
    return 0;
}

Usage:

shellsession
$ gcc main.c $(pkg-config nix-expr-c --libs --cflags) -o main
$ ./main
Nix version: 2.17

Writing a Nix language plug-in

In this example we add a custom primitive operation (primop) to builtins. It
will increment the argument if it is an integer and throw an error otherwise.

plugin.c:

c
#include <nix_api_util.h>
#include <nix_api_expr.h>
#include <nix_api_value.h>

void increment(void* user_data, nix_c_context* ctx, EvalState* state, Value** args, Value* v) {
    nix_value_force(NULL, state, args[0]);
    if (nix_get_type(NULL, args[0]) == NIX_TYPE_INT) {
      nix_init_int(NULL, v, nix_get_int(NULL, args[0]) + 1);
    } else {
      nix_set_err_msg(ctx, NIX_ERR_UNKNOWN, "First argument should be an integer.");
    }
}

void nix_plugin_entry() {
  const char* args[] = {"n", NULL};
  PrimOp *p = nix_alloc_primop(NULL, increment, 1, "increment", args, "Example custom built-in function: increments an integer", NULL);
  nix_register_primop(NULL, p);
  nix_gc_decref(NULL, p);
}

Usage:

shellsession
$ gcc plugin.c $(pkg-config nix-expr-c --libs --cflags) -shared -o plugin.so
$ nix --plugin-files ./plugin.so repl
nix-repl> builtins.increment 1
2

Overview (`tests/functional/test-libstoreconsumer/README.md`)

A very simple C++ consumer of the libstore library.

  • Keep it simple. Library consumers expect something simple.
  • No build hook, or any other reinvocations.
  • No more global state than necessary.

Doc Manual Source Advanced Topics Index (`doc/manual/source/advanced-topics/index.md`)

This section lists advanced topics related to builds and builds performance


Doc Manual Source Command Ref Index (`doc/manual/source/command-ref/index.md`)

This section lists commands and options that you can use when you work
with Nix.


Doc Manual Source Development Index (`doc/manual/source/development/index.md`)

Development

Nix is developed on GitHub.
Check the contributing guide if you want to get involved.

This chapter is a collection of guides for making changes to the code and documentation.

If you're not sure where to start, try to compile Nix from source and consider making improvements to documentation.


Doc Manual Source Installation Index (`doc/manual/source/installation/index.md`)

Installation

This section describes how to install and configure Nix for first-time use.

The current recommended option on Linux and MacOS is multi-user.

Multi-user

This installation offers better sharing, improved isolation, and more security
over a single user installation.

This option requires either:

  • Linux running systemd, with SELinux disabled
  • MacOS

Updating to macOS 15 Sequoia

If you recently updated to macOS 15 Sequoia and are getting

console
error: the user '_nixbld1' in the group 'nixbld' does not exist

when running Nix commands, refer to GitHub issue NixOS/nix#10892 for instructions to fix your installation without reinstalling.

console
$ curl -L https://nixos.org/nix/install | sh -s -- --daemon

Single-user

Single-user is not supported on Mac.

warning: installing Nix as root is not supported by this script!

This installation has less requirements than the multi-user install, however it
cannot offer equivalent sharing, isolation, or security.

This option is suitable for systems without systemd.

console
$ curl -L https://nixos.org/nix/install | sh -s -- --no-daemon

Distributions

The Nix community maintains installers for several distributions.

They can be found in the nix-community/nix-installers repository.


Doc Manual Source Language Index (`doc/manual/source/language/index.md`)

Nix Language

The Nix language is designed for conveniently creating and composing derivations – precise descriptions of how contents of existing files are used to derive new files.

Tip

These pages are written as a reference.
If you are learning Nix, nix.dev has a good introduction to the Nix language.

The language is:

  • domain-specific

    The Nix language is purpose-built for working with text files.
    Its most characteristic features are:

    It comes with built-in functions to integrate with the Nix store, which manages files and enables realising derivations declared in the Nix language.

  • declarative

    There is no notion of executing sequential steps.
    Dependencies between operations are established only through data.

  • pure

    Values cannot change during computation.
    Functions always produce the same output if their input does not change.

  • functional

    Functions are like any other value.
    Functions can be assigned to names, taken as arguments, or returned by functions.

  • lazy

    Values are only computed when they are needed.

  • dynamically typed

    Type errors are only detected when expressions are evaluated.

Overview

This is an incomplete overview of language features, by example.

Example Description
Basic values (primitives)
"hello world" A string
```
''
text
multi
  line
   string

''
``` | A multi-line string. Strips common prefixed whitespace. Evaluates to "multi\n line\n  string". |
| # Explanation | A comment. |
| "hello ${ { a = "world"; }.a }"

"1 2 ${toString 3}"

"${pkgs.bash}/bin/sh" | String interpolation (expands to "hello world", "1 2 3", "/nix/store/-bash-/bin/sh") |
| true, false | Booleans |
| null | Null value |
| 123 | An integer |
| 3.141 | A floating point number |
| /etc | An absolute path |
| ./foo.png | A path relative to the file containing this Nix expression |
| ~/.config | A home path. Evaluates to the "/.config". |
| `` | A lookup path for Nix files. Value determined by $NIX_PATH environment variable. |
| Compound values | |
| { x = 1; y = 2; } | An attribute set with attributes named x and y |
| { foo.bar = 1; } | A nested set, equivalent to { foo = { bar = 1; }; } |
| rec { x = "foo"; y = x + "bar"; } | A recursive set, equivalent to { x = "foo"; y = "foobar"; }. |
| [ "foo" "bar" "baz" ]

[ 1 2 3 ]

[ (f 1) { a = 1; b = 2; } [ "c" ] ] | Lists with three elements. |
| Operators | |
| "foo" + "bar" | String concatenation |
| 1 + 2 | Integer addition |
| "foo" == "f" + "oo" | Equality test (evaluates to true) |
| "foo" != "bar" | Inequality test (evaluates to true) |
| !true | Boolean negation |
| { x = 1; y = 2; }.x | Attribute selection (evaluates to 1) |
| { x = 1; y = 2; }.z or 3 | Attribute selection with default (evaluates to 3) |
| { x = 1; y = 2; } // { z = 3; } | Merge two sets (attributes in the right-hand set taking precedence) |
| Control structures | |
| if 1 + 1 == 2 then "yes!" else "no!" | Conditional expression. |
| assert 1 + 1 == 2; "yes!" | Assertion check (evaluates to "yes!"). |
| let x = "foo"; y = "bar"; in x + y | Variable definition. See let-expressions. |
| with builtins; head [ 1 2 3 ] | Add all attributes from the given set to the scope (evaluates to 1).

See with-expressions for details and shadowing caveats. |
| inherit pkgs src; | Adds the variables to the current scope (attribute set or let binding).
Desugars to pkgs = pkgs; src = src;.
See Inheriting attributes. |
| inherit (pkgs) lib stdenv; | Adds the attributes, from the attribute set in parentheses, to the current scope (attribute set or let binding).
Desugars to lib = pkgs.lib; stdenv = pkgs.stdenv;.
See Inheriting attributes. |
| Functions (lambdas) | |
| x: x + 1 | A function that expects an integer and returns it increased by 1. |
| x: y: x + y | Curried function, equivalent to x: (y: x + y). Can be used like a function that takes two arguments and returns their sum. |
| (x: x + 1) 100 | A function call (evaluates to 101) |
| let inc = x: x + 1; in inc (inc (inc 100)) | A function bound to a variable and subsequently called by name (evaluates to 103) |
| { x, y }: x + y | A function that expects a set with required attributes x and y and concatenates them |
| { x, y ? "bar" }: x + y | A function that expects a set with required attribute x and optional y, using "bar" as default value for y |
| { x, y, ... }: x + y | A function that expects a set with required attributes x and y and ignores any other attributes |
| { x, y } @ args: x + y

args @ { x, y }: x + y | A function that expects a set with required attributes x and y, and binds the whole set to args |
| Built-in functions | |
| import ./foo.nix | Load and return Nix expression in given file.
See import. |
| map (x: x + x) [ 1 2 3 ] | Apply a function to every element of a list (evaluates to [ 2 4 6 ]).
See map. |


Doc Manual Source Package Management Index (`doc/manual/source/package-management/index.md`)

This chapter discusses how to do package management with Nix, i.e.,
how to obtain, install, upgrade, and erase packages. This is the
“user’s” perspective of the Nix system — people who want to create
packages should consult the chapter on the Nix language.


Doc Manual Source Protocols Index (`doc/manual/source/protocols/index.md`)

Protocols

This chapter documents various developer-facing interfaces provided by
Nix.


Doc Manual Source Release Notes Index (`doc/manual/source/release-notes/index.md`)

Nix Release Notes

The Nix release cycle is calendar-based as follows:

Nix has a release cycle of roughly 6 weeks.
Notable changes and additions are announced in the release notes for each version.

The supported Nix versions are:

  • The latest release
  • The version used in the stable NixOS release, which is announced in the NixOS release notes.

Bugfixes and security issues are backported to every supported version.
Patch releases are published as needed.


Doc Manual Source Store Index (`doc/manual/source/store/index.md`)

Nix Store

The Nix store is an abstraction to store immutable file system data (such as software packages) that can have dependencies on other such data.

Concretely, albeit using concepts that are only defined in the rest of the chapter, a store consists of:

  • A set of store objects, the immutable file system data.

    This can also be looked at as a map from store paths to store objects.

  • A set of derivations, instructions for building store objects.

    This can also be looked at as a map from store paths to derivations.
    Since store paths to derivations always end in .drv, and store paths to other store objects never do, the two maps can also be combined into one.
    Derivations can also be encoded as store objects too.

  • A build trace, a record of which derivations have been built and what they produced.

    Warning

    The concept of a build trace is currently
    experimental
    and subject to change.

There are multiple types of Nix stores with different capabilities, such as the default one on the local file system (/nix/store) or binary caches.


Doc Manual Source Protocols Binary Cache Index (`doc/manual/source/protocols/binary-cache/index.md`)

Binary Cache

The binary cache format is an interface designed for exposing a store over HTTP.

A binary cache consists of:

  • A nix-cache-info file at the root with remote-side configuration.
  • For each store object:
    • A .narinfo file containing the object's metadata and a (usually relative) URL to the corresponding compressed NAR.
    • A possibly-compressed Nix Archive containing the store object's file system data.
  • For every entry in the build trace, a JSON file at build-trace-v2/<drvBaseName>/<outputName>.doi:
    • the path encodes the key
    • the contents are the value.

The following store types use the binary cache format:


Doc Manual Source Protocols Nix Archive Index (`doc/manual/source/protocols/nix-archive/index.md`)

Nix Archive (NAR) format

This is the complete specification of the Nix Archive format.
The Nix Archive format closely follows the abstract specification of a file system object tree,
because it is designed to serialize exactly that data structure.

The format of this specification is close to Extended Backus–Naur form, with the exception of the str(..) function / parameterized rule, which length-prefixes and pads strings.
This makes the resulting binary format easier to parse.

Regular users do not need to know this information.
But for those interested in exactly how Nix works, e.g. if they are reimplementing it, this information can be useful.

ebnf
nar = str("nix-archive-1"), nar-obj;

nar-obj = str("("), nar-obj-inner, str(")");

nar-obj-inner
  = str("type"), str("regular") regular
  | str("type"), str("symlink") symlink
  | str("type"), str("directory") directory
  ;

regular = [ str("executable"), str("") ], str("contents"), str(contents);

symlink = str("target"), str(target);

(* side condition: directory entries must be ordered by their names *)
directory = { directory-entry };

directory-entry = str("entry"), str("("), str("name"), str(name), str("node"), nar-obj, str(")");

The str function / parameterized rule is defined as follows:

  • str(s) = int(|s|), pad(s);

  • int(n) = the 64-bit little endian representation of the number n

  • pad(s) = the byte sequence s, padded with 0s to a multiple of 8 byte

Kaitai Struct Specification

The Nix Archive (NAR) format is also formally described using Kaitai Struct, an Interface Description Language (IDL) for defining binary data structures.

Kaitai Struct provides a language-agnostic, machine-readable specification that can be compiled into parsers for various programming languages (e.g., C++, Python, Java, Rust).

yaml
{{#include nar.ksy}}

The source of the spec can be found here. Contributions and improvements to the spec are welcomed.


Doc Manual Source Store Derivation Index (`doc/manual/source/store/derivation/index.md`)

Store Derivation and Deriving Path

Besides functioning as a content-addressed store, the Nix store layer works as a build system.
Other systems (like Git or IPFS) also store and transfer immutable data, but they don't concern themselves with how that data was created.

This is where Nix distinguishes itself.
Derivations represent individual build steps, and deriving paths are needed to refer to the outputs of those build steps before they are built.

Store Derivation {#store-derivation}

A derivation is a specification for running an executable on precisely defined input to produce one or more store objects.
These store objects are known as the derivation's outputs.

Derivations are built, in which case the process is spawned according to the spec, and when it exits, required to leave behind files which will (after post-processing) become the outputs of the derivation.
This process is described in detail in Building.

A derivation consists of:

Referencing derivations {#derivation-path}

Derivations are always referred to by the store path of the store object they are encoded to.
See the encoding section for more details on how this encoding works, and thus what exactly what store path we would end up with for a given derivation.

The store path of the store object which encodes a derivation is often called a derivation path for brevity.

Deriving path {#deriving-path}

Deriving paths are a way to refer to store objects that may or may not yet be realised.
There are two forms:

  • [constant]{#deriving-path-constant}: just a store path.
    It can be made valid by copying it into the store: from the evaluator, command line interface or another store.

  • [output]{#deriving-path-output}: a pair of a store path to a store derivation and an output name.

In pseudo code:

typescript
type OutputName = String;

type ConstantPath = {
  path: StorePath;
};

type OutputPath = {
  drvPath: StorePath;
  output: OutputName;
};

type DerivingPath = ConstantPath | OutputPath;

Deriving paths are necessary because, in general and particularly for content-addressing derivations, the store path of an output is not known in advance.
We can use an output deriving path to refer to such an output, instead of the store path which we do not yet know.

Parts of a derivation

A derivation is constructed from the parts documented in the following subsections.

Inputs {#inputs}

The inputs are a set of deriving paths, referring to all store objects needed in order to perform this build step.

The process creation fields will presumably include many store paths:

  • The path to the executable normally starts with a store path
  • The arguments and environment variables likely contain many other store paths.

But rather than somehow scanning all the other fields for inputs, Nix requires that all inputs be explicitly collected in the inputs field. It is instead the responsibility of the creator of a derivation (e.g. the evaluator) to ensure that every store object referenced in another field (e.g. referenced by store path) is included in this inputs field.

System {#system}

The system type on which the builder executable is meant to be run.

A necessary condition for Nix to schedule a given derivation on some Nix instance is for the "system" of that derivation to match that instance's system configuration option or extra-platforms configuration option.

By putting the system in each derivation, Nix allows heterogeneous build plans, where not all steps can be run on the same machine or same sort of machine.
Nix can schedule builds such that it automatically builds on other platforms by forwarding build requests to other Nix instances.

Process creation fields {#process-creation-fields}

These are the three fields which describe how to spawn the process which (along with any of its own child processes) will perform the build.
You may note that this has everything needed for an execve system call.

Builder {#builder}

This is the path to an executable that will perform the build and produce the outputs.

Arguments {#args}

Command-line arguments to be passed to the builder executable.

Note that these are the arguments after the first argument.
The first argument passed to the builder will be the value of builder, as per the usual convention on Unix.
See Wikipedia for details.

Environment Variables {#env}

Environment variables which will be passed to the builder executable.

Each environment variable additionally has a [pass as file]{#pass-as-file} flag.
When it is set, rather than passing the value directly in the environment, the value is written to a temporary file in the build directory, and an environment variable named like the original but with a Path suffix is set to the path of that file.
For example, a variable big with pass as file set results in an environment variable bigPath pointing to a file containing the value of big.
This is useful for large values, since most operating systems impose a limit on the size of the process environment (typically a few hundred kilobytes).

This flag has no effect when structured attributes are used, as attributes are then not passed through the environment in the first place, so there is no size constraint to avoid.

Structured Attributes {#structured-attrs}

Nix also has special support for embedding JSON in the derivations.

Structured attributes obviate the need for the pass as file flag, since JSON files have no size restrictions, unlike process environments.
They also allow options and output checks to be expressed in a structured way, rather than string-encoded in environment variables.

The environment variable NIX_ATTRS_JSON_FILE points to the exact location of that file both in a build and a nix-shell.

As a convenience to Bash builders, Nix writes a script that initialises shell variables corresponding to all attributes that are representable in Bash.
The environment variable NIX_ATTRS_SH_FILE points to the exact location of the script, both in a build and a nix-shell.
This includes non-nested (associative) arrays.
For example, the attribute hardening.format = true ends up as the Bash associative array element ${hardening[format]}.

Options {#options}

Derivations carry a number of options influencing how they are built and scheduled.
Historically, these were encoded with specially-named environment variables or structured attributes; they are, however, fields of the derivation in their own right.

Options that apply to individual outputs — output checks and reference scanning — are documented with derivation outputs.
The remaining options apply to the derivation as a whole:

  • [export references graph]{#export-references-graph}:
    A map from file names to sets of deriving paths.
    For each entry, the references graph of the given store objects — each store object in their closure, along with its references — is made available to the builder:
    as a file of the given name in the build directory (in the textual format understood by nix-store --register-validity, with the deriver fields left empty and no hashes),
    or, with structured attributes, under the given key in the JSON attributes file (as a list of store object infos).

    This lets a builder do something with the closure of its inputs.

    Usage note

    Examples of builders using this include the builders in NixOS that generate the initial ramdisk for booting Linux (a cpio archive containing the closure of the boot script)
    and the ISO-9660 image for the installation CD (which is populated with a Nix store containing the closure of a bootable NixOS configuration).

  • [required system features]{#required-system-features}:
    A set of features that Nix must have among its system-features for the derivation to be scheduled on it, in addition to the system type matching.

  • [prefer local build]{#prefer-local-build}:
    A hint that the derivation is cheapest to build locally: when distributed building is enabled, it will, if possible, be built locally rather than forwarded to a remote machine.

  • [allow substitutes]{#allow-substitutes}:
    Whether the derivation's outputs may be substituted.
    When disabled, the derivation is always built (locally or remotely); this is useful for derivations that are cheaper to build than to substitute.
    Nix may ignore this option via the always-allow-substitutes configuration option.

    Note

    When disabled, some Nix instance must be able to run the builder on the specified system type, since the derivation cannot be substituted.

  • [impure environment variables]{#impure-env-vars}:
    A set of environment variables passed from the environment of the calling user to the builder, which otherwise starts from a cleared environment.
    This is only allowed for fixed-output derivations, where such impurities are tolerable because (the hash of) the output is known in advance.
    It is ignored for all other derivations.

    Warning

    The variables are taken from the environment of the building process itself:
    when building via a daemon, from the daemon's environment, and only otherwise from the environment of the calling command, e.g. nix-build.

    If the configurable-impure-env experimental feature is enabled,
    these environment variables can also be controlled through the impure-env configuration option.

  • Sandbox-related options:

    • [no chroot]{#no-chroot}:
      The derivation asks to be built without sandboxing.
      Only under certain configurations will this wish actually be respected, however.
      Nix may instead simply fail the build, rather than try to perform it without sandboxing.

    • [additional sandbox profile]{#additional-sandbox-profile}:
      (Darwin only) Additional sandbox profile text, granting the build extra permissions inside the sandbox.

    • [impure host dependencies]{#impure-host-deps}:
      (Darwin only) A set of host system paths made available inside the sandbox.

    • [allow local networking]{#allow-local-networking}:
      (Darwin only) Whether the build may access the local network inside the sandbox.

Placeholders

Placeholders are opaque values used within the process creation fields to store objects for which we don't yet know store paths.
They are strings in the form /<hash> that are embedded anywhere within the strings of those fields, and we are considering to add store-path-like placeholders.

Note

Output Deriving Path exist to solve the same problem as placeholders --- that is, referring to store objects for which we don't yet know a store path.
They also have a string syntax with ^, described in the encoding section.
We could use that syntax instead of /<hash> for placeholders, but its human-legibility would cause problems.

There are two types of placeholder, corresponding to the two cases where this problem arises:

  • [Output placeholder]{#output-placeholder}:

    This is a placeholder for a derivation's own output.

  • [Input placeholder]{#input-placeholder}:

    This is a placeholder to a derivation's non-constant input,
    i.e. an input that is an [output derived path].

Explanation

In general, we need to realise a store object in order to be sure to have a store object for it.
But for these two cases this is either impossible or impractical:

  • In the output case this is impossible:

    We cannot build the output until we have a correct derivation, and we cannot have a correct derivation (without using placeholders) until we have the output path.

  • In the input case this is impractical:

    If we always build a dependency first, and then refer to its output by store path, we would lose the ability for a derivation graph to describe an entire build plan consisting of multiple build steps.

Encoding

Derivation {#derivation-encoding}

There are two formats, documented separately:

Every derivation has a canonical choice of encoding used to serialize it to a store object.
This ensures that there is a canonical store path used to refer to the derivation, as described in Referencing derivations.

Note

Currently, the canonical encoding for every derivation is the "ATerm" format,
but this is subject to change for the types of derivations which are not yet stable.

Regardless of the format used, when serializing a derivation to a store object, that store object will be content-addressed.

In the common case, the inputs to store objects are either:

  • constant deriving paths for content-addressed source objects, which are "initial inputs" rather than the outputs of some other derivation

  • the outputs of other derivations

If those other derivations also abide by this common case (and likewise for transitive inputs), then the entire closure of the serialized derivation will be content-addressed.

Deriving Path {#deriving-path-encoding}

  • constant

    Constant deriving paths are encoded simply as the underlying store path is.
    Thus, we see that every encoded store path is also a valid encoded (constant) deriving path.

  • output

    Output deriving paths are encoded by

    • encoding of a store path referring to a derivation

    • a ^ separator (or ! in some legacy contexts)

    • the name of an output of the previously referred derivation

    Example

    text
    /nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^out

    This parses like so:

    text
    /nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^out
    |------------------------------------------------------------| |-|
    store path (usual encoding)                                    output name
                                                              |--|
                                                              note the ".drv"

Extending the model to be higher-order {#dynamic}

Experimental feature: dynamic-derivations

So far, we have used store paths to refer to derivations.
That works because we've implicitly assumed that all derivations are created statically --- created by some mechanism out of band, and then manually inserted into the store.
But what if derivations could also be created dynamically within Nix?
In other words, what if derivations could be the outputs of other derivations?

Note

In the parlance of "Build Systems à la carte", we are generalizing the Nix store layer to be a "Monadic" instead of "Applicative" build system.

How should we refer to such derivations?
A deriving path works, the same as how we refer to other derivation outputs.
But what about a dynamic derivations output?
(i.e. how do we refer to the output of a derivation, which is itself an output of a derivation?)
For that we need to generalize the definition of deriving path, replacing the store path used to refer to the derivation with a nested deriving path:

diff
type OutputPath = {
-  drvPath: StorePath;
+  drvPath: DerivingPath;
   output: OutputName;
 };

Now, the drvPath field of OutputPath is itself a DerivingPath instead of a StorePath.

With that change, here is updated definition:

typescript
type OutputName = String;

type ConstantPath = {
  path: StorePath;
};

type OutputPath = {
  drvPath: DerivingPath;
  output: OutputName;
};

type DerivingPath = ConstantPath | OutputPath;

Under this extended model, DerivingPaths are thus inductively built up from a root ConstantPath, wrapped with zero or more outer OutputPaths.

Encoding {#deriving-path-encoding-higher-order}

The encoding is adjusted in the natural way, encoding the drv field recursively using the same deriving path encoding.
The result of this is that it is possible to have a chain of ^<output-name> at the end of the final string, as opposed to just a single one.

Example

text
/nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^foo.drv^bar.drv^out
|----------------------------------------------------------------------------| |-|
inner deriving path (usual encoding)                                           output name
|--------------------------------------------------------------------| |-----|
even more inner deriving path (usual encoding)                         output name
|------------------------------------------------------------| |-----|
innermost constant store path (usual encoding)                 output name

Doc Manual Source Store Derivation Outputs Index (`doc/manual/source/store/derivation/outputs/index.md`)

Derivation Outputs and Types of Derivations

As stated on the main pages on derivations,
a derivation produces store objects, which are known as the outputs of the derivation.
Indeed, the entire point of derivations is to produce these outputs, and to reliably and reproducibly produce these derivations each time the derivation is run.

One of the parts of a derivation is its outputs specification, which specifies certain information about the outputs the derivation produces when run.
The outputs specification is a map, from names to specifications for individual outputs.

Output Names {#outputs}

Output names can be any string which is also a valid store path name.
The name mapped to each output specification is not actually the name of the output.
In the general case, the output store object has name derivationName + "-" + outputSpecName, not any other metadata about it.
However, an output spec named "out" describes and output store object whose name is just the derivation name.

Example

A derivation is named hello, and has two outputs, out, and dev

  • The derivation's path will be: /nix/store/<hash>-hello.drv.

  • The store path of out will be: /nix/store/<hash>-hello.

  • The store path of dev will be: /nix/store/<hash>-hello-dev.

The outputs are the derivations are the store objects it is obligated to produce.

Note

The formal terminology here is somewhat at odds with everyday communication in the Nix community today.
"output" in casual usage tends to refer to either to the actual output store object, or the notional output spec, depending on context.

For example "hello's dev output" means the store object referred to by the store path /nix/store/<hash>-hello-dev.
It is unusual to call this the "hello-dev output", even though hello-dev is the actual name of that store object.

Types of output addressing

The main information contained in an output specification is how the derivation output is addressed.
In particular, the specification decides:

Output checks {#output-checks}

In addition to the output specification above, a derivation may mandate additional checks on its outputs:
properties that must hold for the produced store objects in order for the build to be considered successful.
Checks may be specified separately for each output, or once for all outputs of the derivation.

Reference checks

The main checks constrain the references of an output.
These checks vary along two axes, yielding 4 possible checks:

  • Whether the check applies to the direct references of the output, or to its entire closure via transitive references (requisites).

  • Whether the check allows a set of references (every reference must be a member of the set, though not every member needs to be referenced), or disallows a set of references (no reference may be a member of the set).

The four checks are:

  • [allowed references]{#allowed-references}:
    An optional set; the output's references must be a subset of it.
    When the set is absent the check is skipped, i.e. every reference is allowed.

    For example, the empty set enforces that the output has no runtime dependencies at all.

    Usage note

    This is used in NixOS to check that generated files such as initial ramdisks for booting Linux don't have accidental dependencies on other paths in the Nix store.

  • [allowed requisites]{#allowed-requisites}:
    Like allowed references, but applying to the whole closure of the output:
    every transitive dependency must be a member of the set.

  • [disallowed references]{#disallowed-references}:
    A set of which no member may be a direct reference of the output.
    (There is no need for this check to be optional: disallowing nothing is the same as skipping the check.)

  • [disallowed requisites]{#disallowed-requisites}:
    Like disallowed references, but applying to the whole closure of the output:
    no member of the set may appear anywhere in the output's transitive dependencies.

The references of a store object are always store paths.
However, if every element of these sets had to be a store path, it would be hard-to-impossible to constrain references from outputs to other outputs of the same derivation, because in general the store paths of outputs are not known until the derivation is built.
For this reason, an element of these sets may also be an output name of the derivation being checked, standing for the store path of that output, whatever it turns out to be.
For example, an output can be permitted to reference itself by including its own name in its allowed references.

Size checks

  • [max size]{#max-size}:
    The NAR size of the output's store object may not exceed the given number of bytes.

  • [max closure size]{#max-closure-size}:
    The closure NAR size of the output's store object may not exceed the given number of bytes.

Self-reference handling

  • [ignore self references]{#ignore-self-refs}:
    Whether references of an output to itself are exempted from the reference checks above.

Reference scanning {#reference-scanning}

Besides the output checks, there is one more per-output setting.
It is not a check — nothing is verified about the produced store object — but it is configured in the same per-output manner, so it is documented here:

  • [unsafe discard references]{#unsafe-discard-references}:
    Disables scanning the output for run-time references altogether.
    The output is then registered as having no references, regardless of its contents.

    This is useful, for example, when generating self-contained filesystem images with their own embedded Nix store:
    hashes found inside such an image refer to the embedded store and not to the host's Nix store.

    As the name suggests, this is unsafe: discarding references that are in fact needed at run time makes the closure incomplete, so copying the output elsewhere will not bring its dependencies along.

Types of derivations

The sections on each type of derivation output addressing ended up discussing other attributes of the derivation besides its outputs, such as purity, scheduling, determinism, etc.
This is no concidence; for the type of a derivation is in fact one-for-one with the type of its outputs:

  • A derivation that produces xyz-addressed outputs is an xyz-addressing derivations.

The rules for this are fairly concise:

  • All the outputs must be of the same type / use the same addressing

    • The derivation must have at least one output

    • Additionally, if the outputs are fixed content-addressed, there must be exactly one output, whose specification is mapped from the name out.
      (The name out is special, according to the rules described above.
      Having only one output and calling its specification out means the single output is effectively anonymous; the store path just has the derivation name.)

      (This is an arbitrary restriction that could be lifted.)

  • The output is either fixed or floating, indicating whether the store path is known prior to building it.

    • With fixed content-addressing it is fixed.

      A fixed content-addressing derivation is also called a fixed-output derivation, since that is the only currently-implemented form of fixed-output addressing

    • With floating content-addressing or input-addressing it is floating.

    Thus, historically with Nix, with no experimental features enabled, all outputs are fixed.

  • The derivation may be pure or impure, indicating what read access to the outside world the builder has.

    • An input-addressing derivation must be pure.

      If it is impure, we would have a large problem, because an input-addressed derivation always produces outputs with the same paths.

    • A content-addressing derivation may be pure or impure

    • If it is impure, it may be fixed (typical), or it may be floating if the additional impure-derivations experimental feature is enabled.

    • If it is pure, it must be floating.

    • Pure, fixed content-addressing derivations are not supported

      There is no use for this forth combination.
      The sole purpose of an output's store path being fixed is to support the derivation being impure.


Doc Manual Redirects.Json (`doc/manual/redirects.json`)

{
"index.html": {
"part-advanced-topics": "advanced-topics/index.html",
"chap-tuning-cores-and-jobs": "advanced-topics/cores-vs-jobs.html",
"chap-diff-hook": "advanced-topics/diff-hook.html",
"check-dirs-are-unregistered": "advanced-topics/diff-hook.html#check-dirs-are-unregistered",
"chap-distributed-builds": "command-ref/conf-file.html#conf-builders",
"chap-post-build-hook": "advanced-topics/post-build-hook.html",
"chap-post-build-hook-caveats": "advanced-topics/post-build-hook.html#implementation-caveats",
"chap-writing-nix-expressions": "language/index.html",
"part-command-ref": "command-ref/index.html",
"conf-allow-import-from-derivation": "command-ref/conf-file.html#conf-allow-import-from-derivation",
"conf-allow-new-privileges": "command-ref/conf-file.html#conf-allow-new-privileges",
"conf-allowed-uris": "command-ref/conf-file.html#conf-allowed-uris",
"conf-allowed-users": "command-ref/conf-file.html#conf-allowed-users",
"conf-auto-optimise-store": "command-ref/conf-file.html#conf-auto-optimise-store",
"conf-binary-cache-public-keys": "command-ref/conf-file.html#conf-trusted-public-keys",
"conf-binary-caches": "command-ref/conf-file.html#conf-substituters",
"conf-build-compress-log": "command-ref/conf-file.html#conf-compress-build-log",
"conf-build-cores": "command-ref/conf-file.html#conf-cores",
"conf-build-extra-chroot-dirs": "command-ref/conf-file.html#conf-sandbox-paths",
"conf-build-extra-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"conf-build-fallback": "command-ref/conf-file.html#conf-fallback",
"conf-build-max-jobs": "command-ref/conf-file.html#conf-max-jobs",
"conf-build-max-log-size": "command-ref/conf-file.html#conf-max-build-log-size",
"conf-build-max-silent-time": "command-ref/conf-file.html#conf-max-silent-time",
"conf-build-timeout": "command-ref/conf-file.html#conf-timeout",
"conf-build-use-chroot": "command-ref/conf-file.html#conf-sandbox",
"conf-build-use-sandbox": "command-ref/conf-file.html#conf-sandbox",
"conf-build-use-substitutes": "command-ref/conf-file.html#conf-substitute",
"conf-build-users-group": "command-ref/conf-file.html#conf-build-users-group",
"conf-builders": "command-ref/conf-file.html#conf-builders",
"conf-builders-use-substitutes": "command-ref/conf-file.html#conf-builders-use-substitutes",
"conf-compress-build-log": "command-ref/conf-file.html#conf-compress-build-log",
"conf-connect-timeout": "command-ref/conf-file.html#conf-connect-timeout",
"conf-cores": "command-ref/conf-file.html#conf-cores",
"conf-diff-hook": "command-ref/conf-file.html#conf-diff-hook",
"conf-env-keep-derivations": "command-ref/conf-file.html#conf-keep-env-derivations",
"conf-extra-binary-caches": "command-ref/conf-file.html#conf-substituters",
"conf-extra-platforms": "command-ref/conf-file.html#conf-extra-platforms",
"conf-extra-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"conf-extra-substituters": "command-ref/conf-file.html#conf-substituters",
"conf-fallback": "command-ref/conf-file.html#conf-fallback",
"conf-fsync-metadata": "command-ref/conf-file.html#conf-fsync-metadata",
"conf-gc-keep-derivations": "command-ref/conf-file.html#conf-keep-derivations",
"conf-gc-keep-outputs": "command-ref/conf-file.html#conf-keep-outputs",
"conf-hashed-mirrors": "command-ref/conf-file.html#conf-hashed-mirrors",
"conf-http-connections": "command-ref/conf-file.html#conf-http-connections",
"conf-keep-build-log": "command-ref/conf-file.html#conf-keep-build-log",
"conf-keep-derivations": "command-ref/conf-file.html#conf-keep-derivations",
"conf-keep-env-derivations": "command-ref/conf-file.html#conf-keep-env-derivations",
"conf-keep-outputs": "command-ref/conf-file.html#conf-keep-outputs",
"conf-max-build-log-size": "command-ref/conf-file.html#conf-max-build-log-size",
"conf-max-free": "command-ref/conf-file.html#conf-max-free",
"conf-max-jobs": "command-ref/conf-file.html#conf-max-jobs",
"conf-max-silent-time": "command-ref/conf-file.html#conf-max-silent-time",
"conf-min-free": "command-ref/conf-file.html#conf-min-free",
"conf-narinfo-cache-negative-ttl": "command-ref/conf-file.html#conf-narinfo-cache-negative-ttl",
"conf-narinfo-cache-positive-ttl": "command-ref/conf-file.html#conf-narinfo-cache-positive-ttl",
"conf-netrc-file": "command-ref/conf-file.html#conf-netrc-file",
"conf-plugin-files": "command-ref/conf-file.html#conf-plugin-files",
"conf-post-build-hook": "command-ref/conf-file.html#conf-post-build-hook",
"conf-pre-build-hook": "command-ref/conf-file.html#conf-pre-build-hook",
"conf-require-sigs": "command-ref/conf-file.html#conf-require-sigs",
"conf-restrict-eval": "command-ref/conf-file.html#conf-restrict-eval",
"conf-run-diff-hook": "command-ref/conf-file.html#conf-run-diff-hook",
"conf-sandbox": "command-ref/conf-file.html#conf-sandbox",
"conf-sandbox-dev-shm-size": "command-ref/conf-file.html#conf-sandbox-dev-shm-size",
"conf-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"conf-secret-key-files": "command-ref/conf-file.html#conf-secret-key-files",
"conf-show-trace": "command-ref/conf-file.html#conf-show-trace",
"conf-stalled-download-timeout": "command-ref/conf-file.html#conf-stalled-download-timeout",
"conf-substitute": "command-ref/conf-file.html#conf-substitute",
"conf-substituters": "command-ref/conf-file.html#conf-substituters",
"conf-system": "command-ref/conf-file.html#conf-system",
"conf-system-features": "command-ref/conf-file.html#conf-system-features",
"conf-tarball-ttl": "command-ref/conf-file.html#conf-tarball-ttl",
"conf-timeout": "command-ref/conf-file.html#conf-timeout",
"conf-trace-function-calls": "command-ref/conf-file.html#conf-trace-function-calls",
"conf-trusted-binary-caches": "command-ref/conf-file.html#conf-trusted-substituters",
"conf-trusted-public-keys": "command-ref/conf-file.html#conf-trusted-public-keys",
"conf-trusted-substituters": "command-ref/conf-file.html#conf-trusted-substituters",
"conf-trusted-users": "command-ref/conf-file.html#conf-trusted-users",
"extra-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"sec-conf-file": "command-ref/conf-file.html",
"env-NIX_PATH": "command-ref/env-common.html#env-NIX_PATH",
"env-common": "command-ref/env-common.html",
"envar-remote": "command-ref/env-common.html#env-NIX_REMOTE",
"sec-common-env": "command-ref/env-common.html",
"ch-files": "command-ref/files.html",
"ch-main-commands": "command-ref/main-commands.html",
"opt-out-link": "command-ref/nix-build.html#opt-out-link",
"sec-nix-build": "command-ref/nix-build.html",
"sec-nix-channel": "command-ref/nix-channel.html",
"sec-nix-collect-garbage": "command-ref/nix-collect-garbage.html",
"sec-nix-copy-closure": "command-ref/nix-copy-closure.html",
"sec-nix-daemon": "command-ref/nix-daemon.html",
"refsec-nix-env-install-examples": "command-ref/nix-env/install.html#examples",
"rsec-nix-env-install": "command-ref/nix-env/install.html",
"rsec-nix-env-set": "command-ref/nix-env/set.html",
"rsec-nix-env-set-flag": "command-ref/nix-env/set-flag.html",
"rsec-nix-env-upgrade": "command-ref/nix-env/upgrade.html",
"sec-nix-env": "command-ref/nix-env.html",
"ssec-version-comparisons": "command-ref/nix-env.html#selectors",
"sec-nix-hash": "command-ref/nix-hash.html",
"sec-nix-instantiate": "command-ref/nix-instantiate.html",
"sec-nix-prefetch-url": "command-ref/nix-prefetch-url.html",
"sec-nix-shell": "command-ref/nix-shell.html",
"ssec-nix-shell-shebang": "command-ref/nix-shell.html#use-as-a--interpreter",
"nixref-queries": "command-ref/nix-store/query.html#queries",
"opt-add-root": "command-ref/nix-store/query.html#opt-add-root",
"refsec-nix-store-dump": "command-ref/nix-store/dump.html",
"refsec-nix-store-export": "command-ref/nix-store/export.html",
"refsec-nix-store-import": "command-ref/nix-store/import.html",
"refsec-nix-store-query": "command-ref/nix-store/query.html",
"refsec-nix-store-verify": "command-ref/nix-store/verify.html",
"rsec-nix-store-gc": "command-ref/nix-store/gc.html",
"rsec-nix-store-generate-binary-cache-key": "command-ref/nix-store/generate-binary-cache-key.html",
"rsec-nix-store-realise": "command-ref/nix-store/realise.html",
"rsec-nix-store-serve": "command-ref/nix-store/serve.html",
"sec-nix-store": "command-ref/nix-store.html",
"opt-I": "command-ref/opt-common.html#opt-I",
"opt-attr": "command-ref/opt-common.html#opt-attr",
"opt-common": "command-ref/opt-common.html",
"opt-cores": "command-ref/opt-common.html#opt-cores",
"opt-log-format": "command-ref/opt-common.html#opt-log-format",
"opt-max-jobs": "command-ref/opt-common.html#opt-max-jobs",
"opt-max-silent-time": "command-ref/opt-common.html#opt-max-silent-time",
"opt-timeout": "command-ref/opt-common.html#opt-timeout",
"sec-common-options": "command-ref/opt-common.html",
"ch-utilities": "command-ref/utilities.html",
"chap-hacking": "development/building.html",
"adv-attr-allowSubstitutes": "language/advanced-attributes.html#adv-attr-allowSubstitutes",
"adv-attr-allowedReferences": "language/advanced-attributes.html#adv-attr-allowedReferences",
"adv-attr-allowedRequisites": "language/advanced-attributes.html#adv-attr-allowedRequisites",
"adv-attr-disallowedReferences": "language/advanced-attributes.html#adv-attr-disallowedReferences",
"adv-attr-disallowedRequisites": "language/advanced-attributes.html#adv-attr-disallowedRequisites",
"adv-attr-exportReferencesGraph": "language/advanced-attributes.html#adv-attr-exportReferencesGraph",
"adv-attr-impureEnvVars": "language/advanced-attributes.html#adv-attr-impureEnvVars",
"adv-attr-outputHash": "language/advanced-attributes.html#adv-attr-outputHash",
"adv-attr-outputHashAlgo": "language/advanced-attributes.html#adv-attr-outputHashAlgo",
"adv-attr-outputHashMode": "language/advanced-attributes.html#adv-attr-outputHashMode",
"adv-attr-passAsFile": "language/advanced-attributes.html#adv-attr-passAsFile",
"adv-attr-preferLocalBuild": "language/advanced-attributes.html#adv-attr-preferLocalBuild",
"fixed-output-drvs": "language/advanced-attributes.html#adv-attr-outputHash",
"sec-advanced-attributes": "language/advanced-attributes.html",
"builtin-abort": "language/builtins.html#builtins-abort",
"builtin-add": "language/builtins.html#builtins-add",
"builtin-all": "language/builtins.html#builtins-all",
"builtin-any": "language/builtins.html#builtins-any",
"builtin-attrNames": "language/builtins.html#builtins-attrNames",
"builtin-attrValues": "language/builtins.html#builtins-attrValues",
"builtin-baseNameOf": "language/builtins.html#builtins-baseNameOf",
"builtin-bitAnd": "language/builtins.html#builtins-bitAnd",
"builtin-bitOr": "language/builtins.html#builtins-bitOr",
"builtin-bitXor": "language/builtins.html#builtins-bitXor",
"builtin-builtins": "language/builtins.html#builtins-builtins",
"builtin-compareVersions": "language/builtins.html#builtins-compareVersions",
"builtin-concatLists": "language/builtins.html#builtins-concatLists",
"builtin-concatStringsSep": "language/builtins.html#builtins-concatStringsSep",
"builtin-currentSystem": "language/builtins.html#builtins-currentSystem",
"builtin-deepSeq": "language/builtins.html#builtins-deepSeq",
"builtin-derivation": "language/builtins.html#builtins-derivation",
"builtin-dirOf": "language/builtins.html#builtins-dirOf",
"builtin-div": "language/builtins.html#builtins-div",
"builtin-elem": "language/builtins.html#builtins-elem",
"builtin-elemAt": "language/builtins.html#builtins-elemAt",
"builtin-fetchGit": "language/builtins.html#builtins-fetchGit",
"builtin-fetchTarball": "language/builtins.html#builtins-fetchTarball",
"builtin-fetchurl": "language/builtins.html#builtins-fetchurl",
"builtin-filterSource": "language/builtins.html#builtins-filterSource",
"builtin-foldl-prime": "language/builtins.html#builtins-foldl'",
"builtin-fromJSON": "language/builtins.html#builtins-fromJSON",
"builtin-functionArgs": "language/builtins.html#builtins-functionArgs",
"builtin-genList": "language/builtins.html#builtins-genList",
"builtin-getAttr": "language/builtins.html#builtins-getAttr",
"builtin-getEnv": "language/builtins.html#builtins-getEnv",
"builtin-hasAttr": "language/builtins.html#builtins-hasAttr",
"builtin-hashFile": "language/builtins.html#builtins-hashFile",
"builtin-hashString": "language/builtins.html#builtins-hashString",
"builtin-head": "language/builtins.html#builtins-head",
"builtin-import": "language/builtins.html#builtins-import",
"builtin-intersectAttrs": "language/builtins.html#builtins-intersectAttrs",
"builtin-isAttrs": "language/builtins.html#builtins-isAttrs",
"builtin-isBool": "language/builtins.html#builtins-isBool",
"builtin-isFloat": "language/builtins.html#builtins-isFloat",
"builtin-isFunction": "language/builtins.html#builtins-isFunction",
"builtin-isInt": "language/builtins.html#builtins-isInt",
"builtin-isList": "language/builtins.html#builtins-isList",
"builtin-isNull": "language/builtins.html#builtins-isNull",
"builtin-isString": "language/builtins.html#builtins-isString",
"builtin-length": "language/builtins.html#builtins-length",
"builtin-lessThan": "language/builtins.html#builtins-lessThan",
"builtin-listToAttrs": "language/builtins.html#builtins-listToAttrs",
"builtin-map": "language/builtins.html#builtins-map",
"builtin-match": "language/builtins.html#builtins-match",
"builtin-mul": "language/builtins.html#builtins-mul",
"builtin-parseDrvName": "language/builtins.html#builtins-parseDrvName",
"builtin-path": "language/builtins.html#builtins-path",
"builtin-pathExists": "language/builtins.html#builtins-pathExists",
"builtin-placeholder": "language/builtins.html#builtins-placeholder",
"builtin-readDir": "language/builtins.html#builtins-readDir",
"builtin-readFile": "language/builtins.html#builtins-readFile",
"builtin-removeAttrs": "language/builtins.html#builtins-removeAttrs",
"builtin-replaceStrings": "language/builtins.html#builtins-replaceStrings",
"builtin-seq": "language/builtins.html#builtins-seq",
"builtin-sort": "language/builtins.html#builtins-sort",
"builtin-split": "language/builtins.html#builtins-split",
"builtin-splitVersion": "language/builtins.html#builtins-splitVersion",
"builtin-stringLength": "language/builtins.html#builtins-stringLength",
"builtin-sub": "language/builtins.html#builtins-sub",
"builtin-substring": "language/builtins.html#builtins-substring",
"builtin-tail": "language/builtins.html#builtins-tail",
"builtin-throw": "language/builtins.html#builtins-throw",
"builtin-toFile": "language/builtins.html#builtins-toFile",
"builtin-toJSON": "language/builtins.html#builtins-toJSON",
"builtin-toPath": "language/builtins.html#builtins-toPath",
"builtin-toString": "language/builtins.html#builtins-toString",
"builtin-toXML": "language/builtins.html#builtins-toXML",
"builtin-trace": "language/builtins.html#builtins-trace",
"builtin-tryEval": "language/builtins.html#builtins-tryEval",
"builtin-typeOf": "language/builtins.html#builtins-typeOf",
"ssec-builtins": "language/builtins.html",
"attr-system": "language/derivations.html#attr-system",
"ssec-derivation": "language/derivations.html",
"ch-expression-language": "language/index.html",
"sec-constructs": "language/syntax.html",
"sect-let-language": "language/syntax.html#let-expressions",
"ss-functions": "language/syntax.html#functions",
"sec-language-operators": "language/operators.html",
"table-operators": "language/operators.html",
"ssec-values": "language/types.html",
"gloss-closure": "glossary.html#gloss-closure",
"gloss-derivation": "glossary.html#gloss-derivation",
"gloss-deriver": "glossary.html#gloss-deriver",
"gloss-nar": "glossary.html#gloss-nar",
"gloss-output-path": "glossary.html#gloss-output-path",
"gloss-profile": "glossary.html#gloss-profile",
"gloss-reachable": "glossary.html#gloss-reachable",
"gloss-reference": "glossary.html#gloss-reference",
"gloss-substitute": "glossary.html#gloss-substitute",
"gloss-user-env": "glossary.html#gloss-user-env",
"gloss-validity": "glossary.html#gloss-validity",
"part-glossary": "glossary.html",
"sec-building-source": "installation/building-source.html",
"ch-env-variables": "installation/env-variables.html",
"sec-installer-proxy-settings": "installation/env-variables.html#proxy-environment-variables",
"sec-nix-ssl-cert-file": "installation/env-variables.html#nix_ssl_cert_file",
"sec-nix-ssl-cert-file-with-nix-daemon-and-macos": "installation/env-variables.html#nix_ssl_cert_file",
"chap-installation": "installation/index.html",
"ch-installing-binary": "installation/installing-binary.html",
"sect-macos-installation": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-change-store-prefix": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-encrypted-volume": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-recommended-notes": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-symlink": "installation/installing-binary.html#macos-installation",
"sect-multi-user-installation": "installation/installing-binary.html#multi-user-installation",
"sect-nix-install-binary-tarball": "installation/installing-binary.html#installing-from-a-binary-tarball",
"sect-nix-install-pinned-version-url":
"installation/installing-binary.html#installing-a-pinned-nix-version-from-a-url",
"sect-single-user-installation": "installation/installing-binary.html#single-user-installation",
"ch-installing-source": "installation/installing-source.html",
"ssec-multi-user": "installation/multi-user.html",
"ch-nix-security": "installation/nix-security.html",
"sec-obtaining-source": "installation/obtaining-source.html",
"sec-prerequisites-source": "installation/prerequisites-source.html",
"sec-single-user": "installation/single-user.html",
"ch-supported-platforms": "installation/supported-platforms.html",
"ch-upgrading-nix": "installation/upgrading.html",
"ch-about-nix": "introduction.html",
"chap-introduction": "introduction.html",
"ch-basic-package-mgmt": "package-management/index.html",
"ssec-binary-cache-substituter": "package-management/binary-cache-substituter.html",
"sec-channels": "command-ref/nix-channel.html",
"ssec-copy-closure": "command-ref/nix-copy-closure.html",
"sec-garbage-collection": "package-management/garbage-collection.html",
"ssec-gc-roots": "package-management/garbage-collector-roots.html",
"chap-package-management": "package-management/index.html",
"sec-profiles": "package-management/profiles.html",
"ssec-s3-substituter": "store/types/s3-binary-cache-store.html",
"ssec-s3-substituter-anonymous-reads":
"store/types/s3-binary-cache-store.html#anonymous-reads-to-your-s3-compatible-binary-cache",
"ssec-s3-substituter-authenticated-reads":
"store/types/s3-binary-cache-store.html#authenticated-reads-to-your-s3-binary-cache",
"ssec-s3-substituter-authenticated-writes":
"store/types/s3-binary-cache-store.html#authenticated-writes-to-your-s3-compatible-binary-cache",
"sec-sharing-packages": "package-management/sharing-packages.html",
"ssec-ssh-substituter": "package-management/ssh-substituter.html",
"chap-quick-start": "quick-start.html",
"sec-relnotes": "release-notes/index.html",
"ch-relnotes-0.10.1": "release-notes/rl-0.10.1.html",
"ch-relnotes-0.10": "release-notes/rl-0.10.html",
"ssec-relnotes-0.11": "release-notes/rl-0.11.html",
"ssec-relnotes-0.12": "release-notes/rl-0.12.html",
"ssec-relnotes-0.13": "release-notes/rl-0.13.html",
"ssec-relnotes-0.14": "release-notes/rl-0.14.html",
"ssec-relnotes-0.15": "release-notes/rl-0.15.html",
"ssec-relnotes-0.16": "release-notes/rl-0.16.html",
"ch-relnotes-0.5": "release-notes/rl-0.5.html",
"ch-relnotes-0.6": "release-notes/rl-0.6.html",
"ch-relnotes-0.7": "release-notes/rl-0.7.html",
"ch-relnotes-0.8.1": "release-notes/rl-0.8.1.html",
"ch-relnotes-0.8": "release-notes/rl-0.8.html",
"ch-relnotes-0.9.1": "release-notes/rl-0.9.1.html",
"ch-relnotes-0.9.2": "release-notes/rl-0.9.2.html",
"ch-relnotes-0.9": "release-notes/rl-0.9.html",
"ssec-relnotes-1.0": "release-notes/rl-1.0.html",
"ssec-relnotes-1.1": "release-notes/rl-1.1.html",
"ssec-relnotes-1.10": "release-notes/rl-1.10.html",
"ssec-relnotes-1.11.10": "release-notes/rl-1.11.10.html",
"ssec-relnotes-1.11": "release-notes/rl-1.11.html",
"ssec-relnotes-1.2": "release-notes/rl-1.2.html",
"ssec-relnotes-1.3": "release-notes/rl-1.3.html",
"ssec-relnotes-1.4": "release-notes/rl-1.4.html",
"ssec-relnotes-1.5.1": "release-notes/rl-1.5.html",
"ssec-relnotes-1.5.2": "release-notes/rl-1.5.2.html",
"ssec-relnotes-1.5": "release-notes/rl-1.5.html",
"ssec-relnotes-1.6.1": "release-notes/rl-1.6.1.html",
"ssec-relnotes-1.6.0": "release-notes/rl-1.6.html",
"ssec-relnotes-1.7": "release-notes/rl-1.7.html",
"ssec-relnotes-1.8": "release-notes/rl-1.8.html",
"ssec-relnotes-1.9": "release-notes/rl-1.9.html",
"ssec-relnotes-2.0": "release-notes/rl-2.0.html",
"ssec-relnotes-2.1": "release-notes/rl-2.1.html",
"ssec-relnotes-2.2": "release-notes/rl-2.2.html",
"ssec-relnotes-2.3": "release-notes/rl-2.3.html"
},
"language/types.html": {
"simple-values": "#primitives",
"lists": "#type-list",
"strings": "#type-string",
"attribute-sets": "#type-attrs",
"type-number": "#type-int"
},
"language/syntax.html": {
"scoping-rules": "scope.html",
"string-literal": "string-literals.html"
},
"language/derivations.html": {
"builder-execution": "../store/building.html"
},
"installation/installing-binary.html": {
"linux": "uninstall.html#linux",
"macos": "uninstall.html#macos",
"uninstalling": "uninstall.html"
},
"development/building.html": {
"nix-with-flakes": "#building-nix-with-flakes",
"classic-nix": "#building-nix",
"running-tests": "testing.html#running-tests",
"unit-tests": "testing.html#unit-tests",
"functional-tests": "testing.html#functional-tests",
"debugging-failing-functional-tests": "testing.html#debugging-failing-functional-tests",
"integration-tests": "testing.html#integration-tests",
"installer-tests": "testing.html#installer-tests",
"using-the-ci-generated-installer-for-manual-testing":
"testing.html#using-the-ci-generated-installer-for-manual-testing",
"characterization-testing": "testing.html#characterisation-testing-unit",
"add-a-release-note": "contributing.html#add-a-release-note",
"add-an-entry": "contributing.html#add-an-entry",
"build-process": "contributing.html#build-process",
"reverting": "contributing.html#reverting",
"branches": "contributing.html#branches"
},
"store/store-path.html": {
"store-directory": "#store-directory-path"
},
"glossary.html": {
"gloss-local-store": "store/types/local-store.html",
"package-attribute-set": "#package",
"gloss-chroot-store": "store/types/local-store.html",
"gloss-content-addressed-derivation": "#gloss-content-addressing-derivation"
}
}


Doc Manual Rl Next Auto Call Function Installables (`doc/manual/rl-next/auto-call-function-installables.md`)


synopsis: "`nix run`, `nix search` and `nix bundle` now auto-call functions" issues: 5316 prs: 15895

If an installable given with --file or --expr evaluates to a function, it is now called automatically, provided each of its arguments has a default value or is passed with --arg/--argstr.
This makes nix run, nix search and nix bundle behave like nix build, nix shell, nix-build and nix-env --query.

For example, nix run --impure --expr '{ pkgs ? import <nixpkgs> {} }: pkgs.hello' now works instead of failing with error: attribute 'type' does not exist.

nix eval and nix edit, which show the value itself rather than a package, are unchanged.


Doc Manual Rl Next Cgroup Delegate Controllers (`doc/manual/rl-next/cgroup-delegate-controllers.md`)


synopsis: "Daemon enables cgroup controllers for build cgroups" prs: [16024] issues: [9675]

With use-cgroups, the daemon now enables the cpu, memory, io and pids
controllers in its cgroup's cgroup.subtree_control, so per-build cgroups
expose memory.peak, io.stat etc. instead of only cpu.stat. This requires
the controllers to be delegated to the daemon's cgroup (e.g. systemd
Delegate=yes).


Doc Manual Rl Next Infinite Recursion Start (`doc/manual/rl-next/infinite-recursion-start.md`)


synopsis: Start of infinite recursion is now visible issues: [] prs: [16296]

When Nix reports a trace for an infinitely recursive evaluation,
it will now let you discern the cycle from the code that leads up to the cycle.

Example:

nix eval --expr 'let f = builtins.add f 1; in toString f' --show-trace

text
error:
       … while calling the 'toString' builtin
         at «string»:1:30:
            1| let f = builtins.add f 1; in toString f
             |                              ^

       … entering the infinite recursion

       … while calling the 'add' builtin
         at «string»:1:9:
            1| let f = builtins.add f 1; in toString f
             |         ^

       error: infinite recursion encountered

Doc Manual Rl Next Local Repo Detection (`doc/manual/rl-next/local-repo-detection.md`)


synopsis: "Path-like flake references detect Mercurial checkouts"

A path-like flake reference such as . used to become a git+file: input only inside a Git repository, and a path: input everywhere else.
In a Mercurial checkout that copied the whole directory to the store, .hg and untracked files included, and the flake had no rev.

Such a reference now resolves to hg+file:, so only tracked files are copied.
This needs the hg executable, as hg+file: inputs always did.

Input schemes, including ones from plugin-files, can resolve a path-like flake reference to their own scheme by implementing InputScheme::localRepoURL().


Doc Manual Rl Next Optimise Alias (`doc/manual/rl-next/optimise-alias.md`)


synopsis: Add an alias for optimise. issues: [1902, 11326] prs: [11577, 15997]

Add "optimize" as a linguistic variation of "optimise". Now both the nix-store and nix store commands work with the same spelling.


Doc Manual Rl Next S3 Endpoint Url (`doc/manual/rl-next/s3-endpoint-url.md`)


synopsis: "S3: `endpoint=host:port` fixed, deprecated in favour of full URLs"

Bare host:port values for the endpoint parameter of s3:// store URLs
were misparsed (the host was taken as a URL scheme). This is fixed, but the
bare form and the separate scheme parameter are deprecated: use a full URL
such as endpoint=https://minio.example.com instead.


Doc Manual Rl Next Warn Indentation (`doc/manual/rl-next/warn-indentation.md`)


synopsis: "`builtins.warn` now supports unindented multi-line messages" prs: [14794]

builtins.warn now preserves the formatting of messages that start with a newline instead of adding indentation to align them with the warning prefix.


Doc Manual Source C Api (`doc/manual/source/c-api.md`)

C API

Nix provides a C API with the intent of becoming a stable API, which it is currently not.
It is in development.

See:


Doc Manual Source Glossary (`doc/manual/source/glossary.md`)

Glossary

  • [∅]{#gloss-empty-set}

    The empty set symbol. In the context of profile history, this denotes a package is not present in a particular version of the profile.

  • [ε]{#gloss-epsilon}

    The epsilon symbol. In the context of a package, this means the version is empty. More precisely, the derivation does not have a version attribute.

  • base directory{#gloss-base-directory}

    The location from which relative paths are resolved.

    • For expressions in a file, the base directory is the directory containing that file.
      This is analogous to the directory of a base URL.

    • For expressions written in command line arguments with --expr, the base directory is the current working directory.

  • binary cache{#gloss-binary-cache}

    A binary cache is a Nix store which uses a different format: its
    metadata and signatures are kept in .narinfo files rather than in a
    Nix database. This different format simplifies serving store objects
    over the network, but cannot host builds. Examples of binary caches
    include S3 buckets and the NixOS binary cache.

  • build system{#gloss-build-system}

    Generic term for software that facilitates the building of software by automating the invocation of compilers, linkers, and other tools.

    Nix can be used as a generic build system.
    It has no knowledge of any particular programming language or toolchain.
    These details are specified in derivation expressions.

  • closure{#gloss-closure}

    The closure of a store path is the set of store paths that are
    directly or indirectly “reachable” from that store path; that is,
    it’s the closure of the path under the references relation. For
    a package, the closure of its derivation is equivalent to the
    build-time dependencies, while the closure of its output path is
    equivalent to its runtime dependencies. For correct deployment it
    is necessary to deploy whole closures, since otherwise at runtime
    files could be missing. The command nix-store --query --requisites prints out
    closures of store paths.

    As an example, if the store object at path P contains a reference
    to a store object at path Q, then Q is in the closure of P. Further, if Q
    references R then R is also in the closure of P.

    See References for details.

  • [content address]{#gloss-content-address}

    A
    content address
    is a secure way to reference immutable data.
    The reference is calculated directly from the content of the data being referenced, which means the reference is
    tamper proof
    --- variations of the data should always calculate to distinct content addresses.

    For how Nix uses content addresses, see:

    Software Heritage's writing on Intrinsic and Extrinsic identifiers is also a good introduction to the value of content-addressing over other referencing schemes.

    Besides content addressing, the Nix store also uses input addressing.

  • [content-addressed storage]{#gloss-content-addressed-store}

    The industry term for storage and retrieval systems using content addressing. A Nix store also has input addressing, and metadata.

  • [content-addressed store object]{#gloss-content-addressed-store-object}

    A store object which is content-addressed,
    i.e. whose store path is determined by its contents.
    This includes derivations, the outputs of content-addressing derivations, and the outputs of fixed-output derivations.

    See Content-Addressing Store Objects for details.

  • content-addressing derivation{#gloss-content-addressing-derivation}

    A derivation which has the
    __contentAddressed
    attribute set to true.

  • derivation{#gloss-derivation}

    A derivation can be thought of as a pure function that produces new store objects from existing store objects.

    Derivations are implemented as operating system processes that run in a sandbox.
    This sandbox by default only allows reading from store objects specified as inputs, and only allows writing to designated outputs to be captured as store objects.

    A derivation is typically specified as a derivation expression in the Nix language, and instantiated to a store derivation.
    There are multiple ways of obtaining store objects from store derivations, collectively called realisation.

  • derivation expression{#gloss-derivation-expression}

    A description of a store derivation using the derivation primitive in the Nix language.

  • derivation path{#gloss-derivation-path}

    A store path which uniquely identifies a store derivation.

    See Referencing Store Derivations for details.

    Not to be confused with deriving path.

  • [deriver]{#gloss-deriver}

    The store derivation that produced an output path.

    The deriver for an output path can be queried with the --deriver option to
    nix-store --query.

  • deriving path{#gloss-deriving-path}

    Deriving paths are a way to refer to store objects that might not yet be realised.

    See Deriving Path for details.

    Not to be confused with derivation path.

  • [directed acyclic graph]{#gloss-directed-acyclic-graph}

    A directed acyclic graph (DAG) is graph whose edges are given a direction ("a to b" is not the same edge as "b to a"), and for which no possible path (created by joining together edges) forms a cycle.

    DAGs are very important to Nix.
    In particular, the non-self-references of store object form a cycle.

  • [experimental feature]{#gloss-experimental-feature}

    Not yet stabilized functionality guarded by named experimental feature flags.
    These flags are enabled or disabled with the experimental-features setting.

    See the contribution guide on the purpose and lifecycle of experimental feaures.

  • file system object{#gloss-file-system-object}

    The Nix data model for representing simplified file system data.

    See File System Object for details.

  • fixed-output derivation{#gloss-fixed-output-derivation} (FOD)

    A store derivation where a cryptographic hash of the output is determined in advance using the outputHash attribute, and where the builder executable has access to the network.

  • [hermetic]{#gloss-hermetic}

    An evaluation or build process is hermetic when one can mechanically identify the set of all inputs that may affect it.
    At the build level this is achieved by sandboxing; at the evaluation level by restricting impure access (as in pure evaluation) together with locking or pinning of the fetched inputs, taken transitively over pure fetches.

  • [IFD]{#gloss-ifd}

    Import From Derivation

  • [impure derivation]{#gloss-impure-derivation}

    An experimental feature that allows derivations to be explicitly marked as impure,
    so that they are always rebuilt, and their outputs not reused by subsequent calls to realise them.

  • [input-addressed store object]{#gloss-input-addressed-store-object}

    A store object produced by building a
    non-content-addressed,
    non-fixed-output
    derivation.

    See input-addressing derivation outputs for details.

  • [installable]{#gloss-installable}

    Something that can be realised in the Nix store.

    See installables for nix commands (experimental) for details.

  • instantiate{#gloss-instantiate}, instantiation

    Translate a derivation expression into a store derivation.

    See nix-instantiate, which produces a store derivation from a Nix expression that evaluates to a derivation.

  • [locking]{#gloss-locking}

    In package management, locking is the concept or process of creating a lock file, which maps each mutable evaluation input to an immutable reference, so that future evaluations resolve to the same immutable versions rather than whatever the mutable references currently point to.

  • Nix Archive (NAR){#gloss-nar}

    A Nix ARchive. This is a serialisation of a path in the Nix
    store. It can contain regular files, directories and symbolic
    links. NARs are generated and unpacked using nix-store --dump
    and nix-store --restore.

    See Nix Archive for details.

  • Nix database{#gloss-nix-database}

    An SQlite database to track references between store objects.
    This is an implementation detail of the local store.

    Default location: /nix/var/nix/db.

  • [Nix expression]{#gloss-nix-expression}

    A syntactically valid use of the Nix language.

    Example

    The contents of a .nix file form a Nix expression.

    Nix expressions specify derivation expressions, which are instantiated into the Nix store as store derivations.
    These derivations can then be realised to produce outputs.

    Example

    Building and deploying software using Nix entails writing Nix expressions to describe packages and compositions thereof.

  • Nix instance{#gloss-nix-instance}

    1. An installation of Nix, which includes the presence of a store, and the Nix package manager which operates on that store.
      A local Nix installation and a remote builder are two examples of Nix instances.
    2. A running Nix process, such as the nix command.
  • output{#gloss-output}

    A store object produced by a store derivation.
    See the outputs argument to the derivation function for details.

  • [output closure]{#gloss-output-closure}
    The closure of an output path. It only contains what is [reachable] from the output.

  • output path{#gloss-output-path}

    The store path to the output of a store derivation.

  • package{#package}

    A software package; files that belong together for a particular purpose, and metadata.

    Nix represents files as file system objects, and how they belong together is encoded as references between store objects that contain these file system objects.

    The Nix language allows denoting packages in terms of attribute sets containing:

    • attributes that refer to the files of a package, typically in the form of derivation outputs,
    • attributes with metadata, such as information about how the package is supposed to be used.

    The exact shape of these attribute sets is up to convention.

  • [pinning]{#gloss-pinning}

    Like locking, but a pin only locks a single input.
    A pinning solution may manage a collection of pins,
    but serves the bottom-up purpose of fixing an input's reference on demand,
    whereas locking implies a top down approach where all pins are "coerced" into a single place.
    This "coercion" is generally achieved by means of high-level mechanisms such as programming language module systems.
    Nix does not have such a restrictive module system, as even a flake can use expressions that pin or lock on their own.
    It does not rely on the lock being total, but on a transitive fetching property; see hermeticity.

  • [profile]{#gloss-profile}

    A symlink to the current user environment of a user, e.g.,
    /nix/var/nix/profiles/default.

  • [purity]{#gloss-purity}

    The assumption that equal Nix derivations when run always produce
    the same output. This cannot be guaranteed in general (e.g., a
    builder can rely on external inputs such as the network or the
    system time) but the Nix model assumes it.

  • [reachable]{#gloss-reachable}

    A store path Q is reachable from another store path P if Q
    is in the closure of the references relation.

    See References for details.

  • realise{#gloss-realise}, realisation

    Ensure a store path is valid.

    This can be achieved by:

    See nix-store --realise for a detailed description of the algorithm.

    See also nix-build and nix build (experimental).

  • reference{#gloss-reference}

    An edge from one store object to another.

    See References for details.

    See References for details.

  • [referrer]{#gloss-referrer}

    A reversed edge from one store object to another.

  • requisite{#gloss-requisite}

    A store object [reachable] by a path (chain of references) from a given store object.
    The closure is the set of requisites.

    See References for details.

  • store{#gloss-store}

    A collection of store objects, with operations to manipulate that collection.
    See Nix Store for details.

    There are many types of stores, see Store Types for details.

  • store derivation{#gloss-store-derivation}

    A derivation represented as a store object.

    See Store Derivation for details.

  • store object{#gloss-store-object}

    Part of the contents of a store.

    A store object consists of a file system object, references to other store objects, and other metadata.
    It can be referred to by a store path.

    See Store Object for details.

  • store path{#gloss-store-path}

    The location of a store object in the file system, i.e., an immediate child of the Nix store directory.

    Example

    /nix/store/jf6gn2dzna4nmsfbdxsd7kwhsk6gnnlr-git-2.38.1

    See Store Path for details.

  • string interpolation{#gloss-string-interpolation}

    Expanding expressions enclosed in ${ } within a string, path, or attribute name.

    See String interpolation for details.

  • SRI{#gloss-sri}

    Subresource Integrity (SRI) is a W3C specification for integrity metadata.
    Nix uses the SRI hash format (<algorithm>-) to specify content hashes in a way that is self-describing, since the hash algorithm is part of the format.

  • [substitute]{#gloss-substitute}

    A substitute is a command invocation stored in the Nix database that
    describes how to build a store object, bypassing the normal build
    mechanism (i.e., derivations). Typically, the substitute builds the
    store object by downloading a pre-built version of the store object
    from some server.

  • substituter{#gloss-substituter}

    An additional store{#gloss-store} from which Nix can obtain store objects instead of building them.
    Often the substituter is a binary cache, but any store can serve as substituter.

    See the substituters configuration option for details.

  • [user environment]{#gloss-user-env}

    An automatically generated store object that consists of a set of
    symlinks to “active” applications, i.e., other store paths. These
    are generated automatically by
    nix-env. See profiles.

  • validity{#gloss-validity}

    A store path is valid if all store objects in its closure can be read from the store.

    For a local store, this means:


Doc Manual Source Introduction (`doc/manual/source/introduction.md`)

Introduction

Nix is a purely functional package manager. This means that it
treats packages like values in a purely functional programming language
— packages are built by functions that don’t have
side-effects, and they never change after they have been built. Nix
stores packages in the Nix store, usually the directory
/nix/store, where each package has its own unique subdirectory such
as

text
/nix/store/q06x3jll2yfzckz2bzqak089p43ixkkq-firefox-33.1/

where q06x3jll2yfz… is a unique identifier for the package that
captures all its dependencies (it’s a cryptographic hash of the
package’s build dependency graph). This enables many powerful
features.

Multiple versions

You can have multiple versions or variants of a package
installed at the same time. This is especially important when
different applications have dependencies on different versions of the
same package — it prevents the “DLL hell”. Because of the hashing
scheme, different versions of a package end up in different paths in
the Nix store, so they don’t interfere with each other.

An important consequence is that operations like upgrading or
uninstalling an application cannot break other applications, since
these operations never “destructively” update or delete files that are
used by other packages.

Complete dependencies

Nix helps you make sure that package dependency specifications are
complete. In general, when you’re making a package for a package
management system like RPM, you have to specify for each package what
its dependencies are, but there are no guarantees that this
specification is complete. If you forget a dependency, then the
package will build and work correctly on your machine if you have
the dependency installed, but not on the end user's machine if it's
not there.

Since Nix on the other hand doesn’t install packages in “global”
locations like /usr/bin but in package-specific directories, the
risk of incomplete dependencies is greatly reduced. This is because
tools such as compilers don’t search in per-packages directories such
as /nix/store/5lbfaxb722zp…-openssl-0.9.8d/include, so if a package
builds correctly on your system, this is because you specified the
dependency explicitly. This takes care of the build-time dependencies.

Once a package is built, runtime dependencies are found by scanning
binaries for the hash parts of Nix store paths (such as r8vvq9kq…).
This sounds risky, but it works extremely well.

Multi-user support

Nix has multi-user support. This means that non-privileged users can
securely install software. Each user can have a different profile,
a set of packages in the Nix store that appear in the user’s PATH.
If a user installs a package that another user has already installed
previously, the package won’t be built or downloaded a second time.
At the same time, it is not possible for one user to inject a Trojan
horse into a package that might be used by another user.

Atomic upgrades and rollbacks

Since package management operations never overwrite packages in the
Nix store but just add new versions in different paths, they are
atomic. So during a package upgrade, there is no time window in
which the package has some files from the old version and some files
from the new version — which would be bad because a program might well
crash if it’s started during that period.

And since packages aren’t overwritten, the old versions are still
there after an upgrade. This means that you can roll back to the
old version:

console
$ nix-env --upgrade --attr nixpkgs.some-package
$ nix-env --rollback

Garbage collection

When you uninstall a package like this…

console
$ nix-env --uninstall firefox

the package isn’t deleted from the system right away (after all, you
might want to do a rollback, or it might be in the profiles of other
users). Instead, unused packages can be deleted safely by running the
garbage collector:

console
$ nix-collect-garbage

This deletes all packages that aren’t in use by any user profile or by
a currently running program.

Functional package language

Packages are built from Nix expressions, which is a simple
functional language. A Nix expression describes everything that goes
into a package build task (a “derivation”): other packages, sources,
the build script, environment variables for the build script, etc.
Nix tries very hard to ensure that Nix expressions are
deterministic: building a Nix expression twice should yield the same
result.

Because it’s a functional language, it’s easy to support
building variants of a package: turn the Nix expression into a
function and call it any number of times with the appropriate
arguments. Due to the hashing scheme, variants don’t conflict with
each other in the Nix store.

Transparent source/binary deployment

Nix expressions generally describe how to build a package from
source, so an installation action like

console
$ nix-env --install --attr nixpkgs.firefox

could cause quite a bit of build activity, as not only Firefox but
also all its dependencies (all the way up to the C library and the
compiler) would have to be built, at least if they are not already in the
Nix store. This is a source deployment model. For most users,
building from source is not very pleasant as it takes far too long.
However, Nix can automatically skip building from source and instead
use a binary cache, a web server that provides pre-built
binaries. For instance, when asked to build
/nix/store/b6gvzjyb2pg0…-firefox-33.1 from source, Nix would first
check if the file https://cache.nixos.org/b6gvzjyb2pg0….narinfo
exists, and if so, fetch the pre-built binary referenced from there;
otherwise, it would fall back to building from source.

Nix Packages collection

We provide a large set of Nix expressions containing more than 140,000
existing Unix packages, the Nix Packages collection (Nixpkgs).

Managing build environments

Nix is extremely useful for developers as it makes it easy to
automatically set up the build environment for a package. Given a Nix
expression that describes the dependencies of your package, the
command nix-shell will build or download those dependencies if
they’re not already in your Nix store, and then start a Bash shell in
which all necessary environment variables (such as compiler search
paths) are set.

For example, the following command gets all dependencies of the
Pan newsreader, as described by its
Nix expression
:

console
$ nix-shell '<nixpkgs>' --attr pan

You’re then dropped into a shell where you can edit, build and test
the package:

console
[nix-shell]$ unpackPhase
[nix-shell]$ cd pan-*
[nix-shell]$ configurePhase
[nix-shell]$ buildPhase
[nix-shell]$ ./pan/gui/pan

Portability

Nix runs on Linux, macOS and FreeBSD.

NixOS

NixOS is a Linux distribution based on Nix. It uses Nix not just for
package management but also to manage the system configuration (e.g.,
to build configuration files in /etc). This means, among other
things, that it is easy to roll back the entire configuration of the
system to an earlier state. Also, users can install software without
root privileges. For more information and downloads, see the NixOS
homepage
.

License

Nix is released under the terms of the GNU LGPLv2.1 or (at your
option) any later
version
.


Doc Manual Source Quick Start (`doc/manual/source/quick-start.md`)

Quick Start

This chapter is for impatient people who don't like reading documentation.
For more in-depth information you are kindly referred to subsequent chapters.

  1. Install Nix:

    console
    $ curl -L https://nixos.org/nix/install | sh

    The install script will use sudo, so make sure you have sufficient rights.

    For other installation methods, see the detailed installation instructions.

  2. Run software without installing it permanently:

    console
    $ nix-shell --packages cowsay lolcat

    This downloads the specified packages with all their dependencies, and drops you into a Bash shell where the commands provided by those packages are present.
    This will not affect your normal environment:

    console
    [nix-shell:~]$ cowsay Hello, Nix! | lolcat

    Exiting the shell will make the programs disappear again:

    console
    [nix-shell:~]$ exit
    $ lolcat
    lolcat: command not found
  3. Search for more packages on search.nixos.org to try them out.

  4. Free up storage space:

    console
    $ nix-collect-garbage

Doc Manual Source Advanced Topics Cores Vs Jobs (`doc/manual/source/advanced-topics/cores-vs-jobs.md`)

Tuning Cores and Jobs

Nix has two relevant settings with regards to how your CPU cores will
be utilized: cores and max-jobs. This chapter will talk about what
they are, how they interact, and their configuration trade-offs.

  • max-jobs
    Dictates how many separate derivations will be built at the same
    time. If you set this to zero, the local machine will do no
    builds. Nix will still substitute from binary caches, and build
    remotely if remote builders are configured.

  • cores
    Suggests how many cores each derivation should use. Similar to
    make -j.

The cores setting determines the value of
NIX_BUILD_CORES. NIX_BUILD_CORES is equal to cores, unless
cores equals 0, in which case NIX_BUILD_CORES will be the total
number of cores in the system.

The maximum number of consumed cores is a simple multiplication,
max-jobs * NIX_BUILD_CORES.

The balance on how to set these two independent variables depends upon
each builder's workload and hardware. Here are a few example scenarios
on a machine with 24 cores:

max-jobs cores NIX_BUILD_CORES Maximum Processes Result
1 24 24 24 One derivation will be built at a time, each one can use 24 cores. Undersold if a job can’t use 24 cores.
4 6 6 24 Four derivations will be built at once, each given access to six cores.
12 6 6 72 12 derivations will be built at once, each given access to six cores. This configuration is over-sold. If all 12 derivations being built simultaneously try to use all six cores, the machine's performance will be degraded due to extensive context switching between the 12 builds.
24 1 1 24 24 derivations can build at the same time, each using a single core. Never oversold, but derivations which require many cores will be very slow to compile.
24 0 24 576 24 derivations can build at the same time, each using all the available cores of the machine. Very likely to be oversold, and very likely to suffer context switches.

It is up to the derivations' build script to respect host's requested
cores-per-build by following the value of the NIX_BUILD_CORES
environment variable.


Doc Manual Source Advanced Topics Diff Hook (`doc/manual/source/advanced-topics/diff-hook.md`)

Verifying Build Reproducibility

You can use Nix's diff-hook setting to compare build results. Note
that this hook is only executed if the results differ; it is not used
for determining if the results are the same.

For purposes of demonstration, we'll use the following Nix file,
deterministic.nix for testing:

nix
let
  inherit (import <nixpkgs> {}) runCommand;
in {
  stable = runCommand "stable" {} ''
    touch $out
  '';

  unstable = runCommand "unstable" {} ''
    echo $RANDOM > $out
  '';
}

Additionally, nix.conf contains:

text
diff-hook = /etc/nix/my-diff-hook
run-diff-hook = true

where /etc/nix/my-diff-hook is an executable file containing:

bash
#!/bin/sh
exec >&2
echo "For derivation $3:"
/run/current-system/sw/bin/diff -r "$1" "$2"

The diff hook is executed by the same user and group who ran the build.
However, the diff hook does not have write access to the store path just
built.

Spot-Checking Build Determinism

Verify a path which already exists in the Nix store by passing --check
to the build command.

If the build passes and is deterministic, Nix will exit with a status
code of 0:

console
$ nix-build ./deterministic.nix --attr stable
this derivation will be built:
  /nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv
building '/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv'...
/nix/store/yyxlzw3vqaas7wfp04g0b1xg51f2czgq-stable

$ nix-build ./deterministic.nix --attr stable --check
checking outputs of '/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv'...
/nix/store/yyxlzw3vqaas7wfp04g0b1xg51f2czgq-stable

If the build is not deterministic, Nix will exit with a status code of
1:

console
$ nix-build ./deterministic.nix --attr unstable
this derivation will be built:
  /nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv
building '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv'...
/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable

$ nix-build ./deterministic.nix --attr unstable --check
checking outputs of '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv'...
error: derivation '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv' may
not be deterministic: output '/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable' differs

In the Nix daemon's log, we will now see:

text
For derivation /nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv:
1c1
< 8108
---
> 30204

Using --check with --keep-failed will cause Nix to keep the second
build's output in a special, .check path:

console
$ nix-build ./deterministic.nix --attr unstable --check --keep-failed
checking outputs of '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv'...
note: keeping build directory '/tmp/nix-build-unstable.drv-0'
error: derivation '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv' may
not be deterministic: output '/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable' differs
from '/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable.check'

In particular, notice the
/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable.check output. Nix
has copied the build results to that directory where you can examine it.

[]{#check-dirs-are-unregistered} Note

Check paths are not protected against garbage collection, and this
path will be deleted on the next garbage collection.

The path is guaranteed to be alive for the duration of
the diff-hook's execution, but may be deleted any time after.

If the comparison is performed as part of automated tooling, please
use the diff-hook or author your tooling to handle the case where the
build was not deterministic and also a check path does not exist.

--check is only usable if the derivation has been built on the system
already. If the derivation has not been built Nix will fail with the
error:

text
error: some outputs of '/nix/store/hzi1h60z2qf0nb85iwnpvrai3j2w7rr6-unstable.drv' 
are not valid, so checking is not possible

Run the build without --check, and then try with --check again.


Doc Manual Source Advanced Topics Distributed Builds (`doc/manual/source/advanced-topics/distributed-builds.md`)

Remote Builds

A local Nix installation can forward Nix builds to other machines,
this allows multiple builds to be performed in parallel.

Remote builds also allow Nix to perform multi-platform builds in a
semi-transparent way. For example, if you perform a build for a
aarch64-darwin on an i686-linux machine, Nix can automatically
forward the build to a aarch64-darwin machine, if one is available.

Requirements

For a local machine to forward a build to a remote machine, the remote machine must:

  • Have Nix installed
  • Be running an SSH server, e.g. sshd
  • Be accessible via SSH from the local machine over the network
  • Have the local machine's public SSH key in /etc/ssh/authorized_keys.d/
  • Have the username of the SSH user in the trusted-users setting in nix.conf

Testing

To test connecting to a remote Nix instance (in this case mac), run:

console
nix store info --store ssh://username@mac

To specify an SSH identity file as part of the remote store URI add a
query parameter, e.g.

console
nix store info --store ssh://username@mac?ssh-key=/home/alice/my-key

Since builds should be non-interactive, the key should not have a
passphrase. Alternatively, you can load identities ahead of time into
ssh-agent or gpg-agent.

In a multi-user installation (default), builds are executed by the Nix
Daemon. The Nix Daemon cannot prompt for a passphrase via the terminal
or ssh-agent, so the SSH key must not have a passphrase.

In addition, the Nix Daemon's user (typically root) needs to have SSH
access to the remote builder.

Access can be verified by running sudo su, and then validating SSH
access, e.g. by running ssh mac. SSH identity files for root users
are usually stored in /root/.ssh/ (Linux) or /var/root/.ssh (MacOS).

If you get the error

console
bash: nix: command not found
error: cannot connect to 'mac'

then you need to ensure that the PATH of non-interactive login shells
contains Nix.

The list of remote build machines can be specified on the command line or in the Nix configuration file.
For example, the following command allows you to build a derivation for aarch64-darwin on a Linux machine:

console
uname
console
Linux
console
nix build --impure \
 --expr '(with import <nixpkgs> { system = "aarch64-darwin"; }; runCommand "foo" {} "uname > $out")' \
 --builders 'ssh://mac aarch64-darwin'
console
[1/0/1 built, 0.0 MiB DL] building foo on ssh://mac
console
cat ./result
console
Darwin

It is possible to specify multiple build machines separated by a semicolon or a newline, e.g.

console
--builders 'ssh://mac aarch64-darwin ; ssh://beastie x86_64-freebsd'

Remote build machines can also be configured in nix.conf, e.g.

text
builders = ssh://mac aarch64-darwin ; ssh://beastie x86_64-freebsd

After making changes to nix.conf, restart the Nix daemon for changes to take effect.

Finally, remote build machines can be configured in a separate configuration
file included in builders via the syntax @/path/to/file. For example,

text
builders = @/etc/nix/machines

causes the list of machines in /etc/nix/machines to be included.
(This is the default.)


Doc Manual Source Advanced Topics Eval Profiler (`doc/manual/source/advanced-topics/eval-profiler.md`)

Using the `eval-profiler`

Nix evaluator supports evaluation
profiling
compatible with flamegraph.pl. The profiler samples the nix
function call stack at regular intervals. It can be enabled with the
eval-profiler
setting:

console
$ nix-instantiate "<nixpkgs>" -A hello --eval-profiler flamegraph

Stack sampling frequency and the output file path can be configured with
eval-profile-file
and eval-profiler-frequency.
By default the collected profile is saved to nix.profile file in the current working directory.

The collected profile can be directly consumed by flamegraph.pl:

console
$ flamegraph.pl nix.profile > flamegraph.svg

The line information in the profile contains the location of the call
site
position and the name of the
function being called (when available). For example:

text
/nix/store/2q71fdvr4h33g9832hiriwnf20fn630l-source/pkgs/top-level/default.nix:167:5:primop import

Here import primop is called at /nix/store/2q71fdvr4h33g9832hiriwnf20fn630l-source/pkgs/top-level/default.nix:167:5.


Doc Manual Source Advanced Topics Post Build Hook (`doc/manual/source/advanced-topics/post-build-hook.md`)

Using the `post-build-hook`

Implementation Caveats

Here we use the post-build hook to upload to a binary cache. This is a
simple and working example, but it is not suitable for all use cases.

The post build hook program runs after each executed build, and blocks
the build loop. The build loop exits if the hook program fails.

Concretely, this implementation will make Nix slow or unusable when the
internet is slow or unreliable.

A more advanced implementation might pass the store paths to a
user-supplied daemon or queue for processing the store paths outside of
the build loop.

Prerequisites

This tutorial assumes you have configured an S3-compatible binary cache as a substituter,
and that the root user's default AWS profile can upload to the bucket.

Set up a Signing Key

Use nix-store --generate-binary-cache-key to create our public and
private signing keys. We will sign paths with the private key, and
distribute the public key for verifying the authenticity of the paths.

console
# nix-store --generate-binary-cache-key example-nix-cache-1 /etc/nix/key.private /etc/nix/key.public
# cat /etc/nix/key.public
example-nix-cache-1:1/cKDz3QCCOmwcztD2eV6Coggp6rqc9DGjWv7C0G+rM=

Then update nix.conf on any machine that will access the cache.
Add the cache URL to substituters and the public key to trusted-public-keys:

text
substituters = https://cache.nixos.org/ s3://example-nix-cache
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= example-nix-cache-1:1/cKDz3QCCOmwcztD2eV6Coggp6rqc9DGjWv7C0G+rM=

Machines that build for the cache must sign derivations using the private key.
On those machines, add the path to the key file to the secret-key-files field in their nix.conf:

text
secret-key-files = /etc/nix/key.private

We will restart the Nix daemon in a later step.

Implementing the build hook

Write the following script to /etc/nix/upload-to-cache.sh:

bash
#!/bin/sh

set -eu
set -f # disable globbing
export IFS=' '

echo "Uploading paths" $OUT_PATHS
exec nix copy --to "s3://example-nix-cache" $OUT_PATHS

Note

The $OUT_PATHS variable is a space-separated list of Nix store
paths. In this case, we expect and want the shell to perform word
splitting to make each output path its own argument to nix store sign. Nix guarantees the paths will not contain any spaces,
however a store path might contain glob characters. The set -f
disables globbing in the shell.
If you want to upload the .drv file too, the $DRV_PATH variable
is also defined for the script and works just like $OUT_PATHS.

Then make sure the hook program is executable by the root user:

console
# chmod +x /etc/nix/upload-to-cache.sh

Updating Nix Configuration

Edit /etc/nix/nix.conf to run our hook, by adding the following
configuration snippet at the end:

text
post-build-hook = /etc/nix/upload-to-cache.sh

Then, restart the nix-daemon.

Testing

Build any derivation, for example:

console
$ nix-build --expr '(import <nixpkgs> {}).writeText "example" (builtins.toString builtins.currentTime)'
this derivation will be built:
  /nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv
building '/nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv'...
running post-build-hook '/home/grahamc/projects/github.com/NixOS/nix/post-hook.sh'...
post-build-hook: Signing paths /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
post-build-hook: Uploading paths /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
/nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example

Then delete the path from the store, and try substituting it from the
binary cache:

console
$ rm ./result
$ nix-store --delete /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example

Now, copy the path back from the cache:

console
$ nix-store --realise /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
copying path '/nix/store/m8bmqwrch6l3h8s0k3d673xpmipcdpsa-example from 's3://example-nix-cache'...
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
/nix/store/m8bmqwrch6l3h8s0k3d673xpmipcdpsa-example

Conclusion

We now have a Nix installation configured to automatically sign and
upload every local build to a remote binary cache.

Before deploying this to production, be sure to consider the
implementation caveats.


Doc Manual Source Architecture Architecture (`doc/manual/source/architecture/architecture.md`)

Architecture

This chapter describes how Nix works.
It should help users understand why Nix behaves as it does, and it should help developers understand how to modify Nix and how to write similar tools.

Overview

Nix consists of hierarchical layers.

The following concept map shows its main components (rectangles), the objects they operate on (rounded rectangles), and their interactions (connecting phrases):

text
/* Detailed source-code truncated for AI context efficiency. */

At the top is the command line interface that drives the underlying layers.

The Nix language evaluator transforms Nix expressions into self-contained build plans, which are used to derive build results from referenced build inputs.

The command line interface and Nix expressions are what users deal with most.

Note

The Nix language itself does not have a notion of packages or configurations.
As far as we are concerned here, the inputs and results of a build plan are just data.

Underlying the command line interface and the Nix language evaluator is the Nix store, a mechanism to keep track of build plans, data, and references between them.
It can also execute build plans to produce new data, which are made available to the operating system as files.

A build plan itself is a series of build tasks, together with their build inputs.

Important
A build task in Nix is called store derivation.

Each build task has a special build input executed as build instructions in order to perform the build.
The result of a build task can be input to another build task.

The following data flow diagram shows a build plan for illustration.
Build inputs used as instructions to a build task are marked accordingly:

text
/* Detailed source-code truncated for AI context efficiency. */

Doc Manual Source Command Ref Conf File Prefix (`doc/manual/source/command-ref/conf-file-prefix.md`)

Name

nix.conf - Nix configuration file

Description

Nix supports a variety of configuration settings, which are read from configuration files or taken as command line flags.

Configuration file

By default Nix reads settings from each of the following places.
Settings are applied on top of one another, so later settings overwrite earlier entries.

  1. The system-wide configuration file nix.conf in the configuration directory.

    The configuration directory defaults to ${sysconfdir}/nix (i.e. /etc/nix on most Unix systems) or %PROGRAMDATA%\nix\conf on Windows, and can be overridden with NIX_CONF_DIR.

    Values loaded in this file are not forwarded to the Nix daemon.
    The client assumes that the daemon has already loaded them.

  2. If NIX_USER_CONF_FILES is set, then each path in the list will be loaded in reverse order.
    The list separator is : on Unix and ; on Windows.

    Otherwise it will look for nix.conf in:

  3. If NIX_CONFIG is set, its contents are treated as the contents of a configuration file.
    In particular, settings are separated by newlines, just as in the configuration file.

File format

Configuration files consist of name = value pairs, one per line.
Comments start with a # character.

Example:

text
keep-outputs = true       # Nice for developers
keep-derivations = true   # Idem

Other files can be included with a line like include , where `` is interpreted relative to the current configuration file.
A missing file is an error unless !include is used instead.

A configuration setting usually overrides any previous value.
However, for settings that take a list of items, you can prefix the name of the setting by extra- to append to the previous value.

For instance,

text
substituters = a b
extra-substituters = c d

defines the substituters setting to be a b c d.

Unknown option names are not an error, and are simply ignored with a warning.

Command line flags

Configuration options can be set on the command line, overriding the values set in the configuration file:

  • Every configuration setting has corresponding command line flag (e.g. --max-jobs 16).
    Boolean settings do not need an argument, and can be explicitly disabled with the no- prefix (e.g. --keep-failed and --no-keep-failed).

    Unknown option names are invalid flags (unless there is already a flag with that name), and are rejected with an error.

  • The flag --option <name> <value> is interpreted exactly like a <name> = <value> in a setting file.

    Unknown option names are ignored with a warning.

The extra- prefix is supported for settings that take a list of items (e.g. --extra-trusted users alice or --option extra-trusted-users alice).

Integer settings

Settings that have an integer type support the suffixes K, M, G
and T. These cause the specified value to be multiplied by 2^10,
2^20, 2^30 and 2^40, respectively. For instance, --min-free 1M is
equivalent to --min-free 1048576.

Available settings


Doc Manual Source Command Ref Env Common (`doc/manual/source/command-ref/env-common.md`)

Common Environment Variables

Most Nix commands interpret the following environment variables.

Configuration environment variables

The following environment variables affect how Nix loads its configuration.
See the configuration file documentation for full details.

Store setting environment variables

  • NIX_IGNORE_SYMLINK_STORE

    Normally, the Nix store directory (typically /nix/store) is not
    allowed to contain any symlink components. This is to prevent
    “impure” builds. Builders sometimes “canonicalise” paths by
    resolving all symlink components. Thus, builds on different machines
    (with /nix/store resolving to different locations) could yield
    different results. This is generally not a problem, except when
    builds are deployed to machines where /nix/store resolves
    differently. If you are sure that you’re not going to do that, you
    can set NIX_IGNORE_SYMLINK_STORE to 1.

    Note that if you’re symlinking the Nix store so that you can put it
    on another file system than the root file system, on Linux you’re
    better off using bind mount points, e.g.,

    console
    $ mkdir /nix
    $ mount -o bind /mnt/otherdisk/nix /nix

    Consult the mount 8 manual page for details.

  • NIX_STORE_DIR

    Overrides the location of the Nix store.
    On Unix, the default is /nix/store, set at compile time by the libstore:store-dir build option.
    On Windows, there is no compile-time setting; the default is %PROGRAMDATA%\nix\store, determined at runtime using the %PROGRAMDATA% Known Folder.

    See the Store Types chapter; each store has a store setting linking back to this as its default.

  • NIX_LOG_DIR

    Overrides the location of the Nix log directory.
    On Unix, the default is /nix/var/log/nix, set at compile time by the log-dir build option.
    On Windows, there is no compile-time setting; the default is %PROGRAMDATA%\nix\log, determined at runtime using the %PROGRAMDATA% Known Folder.

    The Local Store, Local Daemon Store, and Experimental SSH Store with filesystem mounted have per-store settings that override this.

  • NIX_STATE_DIR

    Overrides the location of the Nix state directory.
    On Unix, the default is ${localstatedir}/nix, where localstatedir is a compile-time build option defaulting to /nix/var.
    On Windows, there is no compile-time setting; the default is %PROGRAMDATA%\nix\state, determined at runtime using the %PROGRAMDATA% Known Folder.

    The Local Store, Local Daemon Store, and Experimental SSH Store with filesystem mounted have per-store settings that override this.

  • NIX_DAEMON_SOCKET_PATH

    Overrides the path to the Unix domain socket used to communicate with the Nix daemon.
    Defaults to daemon-socket/socket within the state directory (see NIX_STATE_DIR).

    See the Local Daemon Store documentation for details on how the socket path is resolved.

  • TMPDIR

    Use the specified directory to store temporary files. In particular,
    this includes temporary build directories; these can take up
    substantial amounts of disk space. The default is /tmp.

  • NIX_REMOTE

    Overrides the store setting.

Nix language evaluator settings

  • NIX_SHOW_STATS

    If set to 1, Nix will print some evaluation statistics, such as
    the number of values allocated.

  • NIX_COUNT_CALLS

    If set to 1, Nix will print how often functions were called during
    Nix expression evaluation. This is useful for profiling your Nix
    expressions.

  • GC_INITIAL_HEAP_SIZE

    If Nix has been configured to use the Boehm garbage collector, this
    variable sets the initial size of the heap in bytes. It defaults to
    384 MiB. Setting it to a low value reduces memory consumption, but
    will increase runtime due to the overhead of garbage collection.

  • NIX_PATH

    A colon-separated list of search path entries used to resolve lookup paths.

    This environment variable overrides the value of the nix-path configuration setting.

    It can be extended using the -I option.

    Example

    bash
    $ export NIX_PATH=/home/eelco/Dev:nixos-config=/etc/nixos

    If NIX_PATH is set to an empty string, resolving search paths will always fail.

    Example

    bash
    $ NIX_PATH= nix-instantiate --eval '<nixpkgs>'
    error: file 'nixpkgs' was not found in the Nix search path (add it using $NIX_PATH or -I)

User Directories

Nix supports per-user configuration, state, and cache directories.
The following environment variables override the locations for these directories:

  • [user configuration directory]{#user-conf-dir}: [NIX_CONFIG_HOME]{#env-NIX_CONFIG_HOME}
  • user state directory: [NIX_STATE_HOME]{#env-NIX_STATE_HOME}
  • user cache directory: [NIX_CACHE_HOME]{#env-NIX_CACHE_HOME}

When these are not set, the defaults depend on the platform:

  • On Unix, the XDG base directories: $XDG_CONFIG_HOME/nix, $XDG_STATE_HOME/nix, $XDG_CACHE_HOME/nix
  • On Windows, the Windows Known Folders: %APPDATA%\nix\config, %LOCALAPPDATA%\nix\state, %LOCALAPPDATA%\nix\cache

For backwards compatibility, legacy Nix commands (e.g. nix-env, nix-channel) use dotfiles in $HOME instead of these directories unless use-xdg-base-directories is enabled.
New Nix commands (experimental) use the proper directories by default.

When use-xdg-base-directories is enabled, the configuration directory is resolved as:

  1. $NIX_CONFIG_HOME, if it is defined
  2. Otherwise, the platform default (e.g. $XDG_CONFIG_HOME/nix on Unix)

Likewise for the state and cache directories.

Miscellaneous environment variables

  • IN_NIX_SHELL

    Indicator that tells if the current environment was set up by
    nix-shell. It can have the values pure or impure.

Appendix: OS-specific conventions

This information is not Nix-specific, but is referenced above.

Unix: XDG Base Directories {#xdg-base-directories}

The XDG Base Directory Specification defines standard locations for user-specific configuration, state, and cache files on Unix systems.

The following environment variables are used:

  • [XDG_CONFIG_HOME]{#env-XDG_CONFIG_HOME} (default ~/.config)
  • [XDG_STATE_HOME]{#env-XDG_STATE_HOME} (default ~/.local/state)
  • [XDG_CACHE_HOME]{#env-XDG_CACHE_HOME} (default ~/.cache)
  • [XDG_CONFIG_DIRS]{#env-XDG_CONFIG_DIRS} (default /etc/xdg) — colon-separated list of additional configuration base directories, searched after XDG_CONFIG_HOME

Windows: Known Folders {#known-folders}

On Windows, Known Folders provide standard locations for application data on Windows.

The relevant folders are:

  • [%APPDATA%]{#env-APPDATA} — per-user roaming application data
  • [%LOCALAPPDATA%]{#env-LOCALAPPDATA} — per-user local application data
  • [%PROGRAMDATA%]{#env-PROGRAMDATA} — system-wide application data

Doc Manual Source Command Ref Experimental Commands (`doc/manual/source/command-ref/experimental-commands.md`)

Experimental Commands

This section lists experimental commands.

Warning

These commands may be removed in the future, or their syntax may
change in incompatible ways.


Doc Manual Source Command Ref Files (`doc/manual/source/command-ref/files.md`)

Files

This section lists configuration files that you can use when you work
with Nix.


Doc Manual Source Command Ref Main Commands (`doc/manual/source/command-ref/main-commands.md`)

Main Commands

This section lists commands and options that you can use when you work
with Nix.


Doc Manual Source Command Ref Nix Build (`doc/manual/source/command-ref/nix-build.md`)

Name

nix-build - build a Nix expression

Synopsis

nix-build [paths…]
[--arg name value]
[--argstr name value]
[{--attr | -A} attrPath]
[--no-out-link]
[--dry-run]
[{--out-link | -o} outlink]

Disambiguation

This man page describes the command nix-build, which is distinct from nix build. For documentation on the latter, run nix build --help or see man nix3-build.

Description

The nix-build command builds the derivations described by the Nix
expressions in paths. If the build succeeds, it places a symlink to
the result in the current directory. The symlink is called result. If
there are multiple Nix expressions, or the Nix expressions evaluate to
multiple derivations, multiple sequentially numbered symlinks are
created (result, result-2, and so on).

If no paths are specified, then nix-build will use default.nix in
the current directory, if it exists.

If an element of paths starts with http:// or https://, it is
interpreted as the URL of a tarball that will be downloaded and unpacked
to a temporary location. The tarball must include a single top-level
directory containing at least a file named default.nix.

nix-build is essentially a wrapper around
nix-instantiate (to translate a high-level Nix
expression to a low-level store derivation) and nix-store --realise (to build the store
derivation).

Warning

The result of the build is automatically registered as a root of the
Nix garbage collector. This root disappears automatically when the
result symlink is deleted or renamed. So don’t rename the symlink.

Options

All options not listed here are passed to
nix-store --realise,
except for --arg and --attr / -A which are passed to nix-instantiate.

  • --no-out-link

    Do not create a symlink to the output path. Note that as a result
    the output does not become a root of the garbage collector, and so
    might be deleted by nix-store --gc.

  • --dry-run

    Show what store paths would be built or downloaded.

  • --out-link / -o outlink

    Change the name of the symlink to the output path created from
    result to outlink.

{{#include ./status-build-failure.md}}

{{#include ./opt-common.md}}

{{#include ./env-common.md}}

Examples

console
$ nix-build '<nixpkgs>' --attr firefox
store derivation is /nix/store/qybprl8sz2lc...-firefox-1.5.0.7.drv
/nix/store/d18hyl92g30l...-firefox-1.5.0.7

$ ls -l result
lrwxrwxrwx  ...  result -> /nix/store/d18hyl92g30l...-firefox-1.5.0.7

$ ls ./result/bin/
firefox  firefox-config

If a derivation has multiple outputs, nix-build will build the default
(first) output. You can also build all outputs:

console
$ nix-build '<nixpkgs>' --attr openssl.all

This will create a symlink for each output named result-outputname.
The suffix is omitted if the output name is out. So if openssl has
outputs out, bin and man, nix-build will create symlinks
result, result-bin and result-man. It’s also possible to build a
specific output:

console
$ nix-build '<nixpkgs>' --attr openssl.man

This will create a symlink result-man.

Build a Nix expression given on the command line:

console
$ nix-build --expr 'with import <nixpkgs> { }; runCommand "foo" { } "echo bar > $out"'
$ cat ./result
bar

Build the GNU Hello package from the latest revision of the master
branch of Nixpkgs:

console
$ nix-build https://github.com/NixOS/nixpkgs/archive/master.tar.gz --attr hello

Doc Manual Source Command Ref Nix Channel (`doc/manual/source/command-ref/nix-channel.md`)

Name

nix-channel - manage Nix channels

Synopsis

nix-channel {--add url [name] | --remove name | --list | --update [names…] | --list-generations | --rollback [generation] }

Description

Channels are a mechanism for referencing remote Nix expressions and conveniently retrieving their latest version.

The moving parts of channels are:

Note

The state of a subscribed channel is external to the Nix expressions relying on it.
This may limit reproducibility.

Dependencies on other Nix expressions can be declared explicitly with:

This command has the following operations:

  • --add url [name]

    Add a channel name located at url to the list of subscribed channels.
    If name is omitted, default to the last component of url, with the suffixes -stable or -unstable removed.

    Note

    --add does not automatically perform an update.
    Use --update explicitly.

    A channel URL must point to a directory containing a file nixexprs.tar.gz.
    At the top level, that tarball must contain a single directory with a default.nix file that serves as the channel’s entry point.

  • --remove name

    Remove the channel name from the list of subscribed channels.

  • --list

    Print the names and URLs of all subscribed channels on standard output.

  • --update [names…]

    Download the Nix expressions of subscribed channels and create a new generation.
    Update all channels if none is specified, and only those included in names otherwise.

    Note

    Downloaded channel contents are cached.
    Use --tarball-ttl or the tarball-ttl configuration option to change the validity period of cached downloads.

  • --list-generations

    Prints a list of all the current existing generations for the
    channel profile.

    Works the same way as

    text
    nix-env --profile /nix/var/nix/profiles/per-user/$USER/channels --list-generations
  • --rollback [generation]

    Revert channels to the state before the last call to nix-channel --update.
    Optionally, you can specify a specific channel generation number to restore.

{{#include ./opt-common.md}}

{{#include ./env-common.md}}

Files

nix-channel operates on the following files.

{{#include ./files/channels.md}}

Examples

Subscribe to the Nixpkgs channel and run hello from the GNU Hello package:

console
$ nix-channel --add https://channels.nixos.org/nixpkgs-unstable
$ nix-channel --list
nixpkgs https://channels.nixos.org/nixpkgs
$ nix-channel --update
$ nix-shell -p hello --run hello
hello

Revert channel updates using --rollback:

console
$ nix-instantiate --eval '<nixpkgs>' --attr lib.version
"22.11pre296212.530a53dcbc9"

$ nix-channel --rollback
switching from generation 483 to 482

$ nix-instantiate --eval '<nixpkgs>' --attr lib.version
"22.11pre281526.d0419badfad"

Remove a channel:

console
$ nix-channel --remove nixpkgs
$ nix-channel --list

Doc Manual Source Command Ref Nix Collect Garbage (`doc/manual/source/command-ref/nix-collect-garbage.md`)

Name

nix-collect-garbage - delete unreachable store objects

Synopsis

nix-collect-garbage [--delete-old] [-d] [--delete-older-than period] [--max-freed bytes] [--dry-run]

Description

The command nix-collect-garbage is mostly an alias of nix-store --gc.
That is, it deletes all unreachable store objects in the Nix store to clean up your system.

However, it provides two additional options,
--delete-old and --delete-older-than,
which also delete old profiles, allowing potentially more store objects to be deleted because profiles are also garbage collection roots.
These options are the equivalent of running
nix-env --delete-generations
with various augments on multiple profiles,
prior to running nix-collect-garbage (or just nix-store --gc) without any flags.

Note

Deleting previous configurations makes rollbacks to them impossible.

These flags should be used with care, because they potentially delete generations of profiles used by other users on the system.

Locations searched for profiles

nix-collect-garbage cannot know about all profiles; that information doesn't exist.
Instead, it looks in a few locations, and acts on all profiles it finds there:

  1. The default profile locations as specified in the profiles section of the manual.

  2. NOTE

    Not stable; subject to change

    Do not rely on this functionality; it just exists for migration purposes and may change in the future.
    These deprecated paths remain a private implementation detail of Nix.

    $NIX_STATE_DIR/profiles and $NIX_STATE_DIR/profiles/per-user.

    With the exception of $NIX_STATE_DIR/profiles/per-user/root and $NIX_STATE_DIR/profiles/default, these directories are no longer used by other commands.
    nix-collect-garbage looks there anyways in order to clean up profiles from older versions of Nix.

Options

These options are for deleting old profiles prior to deleting unreachable store objects.

  • --delete-old / -d

    Delete all old generations of profiles.

    This is the equivalent of invoking nix-env --delete-generations old on each found profile.

  • --delete-older-than period

    Delete all generations of profiles older than the specified amount (except for the generations that were active at that point in time).
    period is a value such as 30d, which would mean 30 days.

    This is the equivalent of invoking nix-env --delete-generations on each found profile.
    See the documentation of that command for additional information about the period argument.

  • --max-freed bytes

    Keep deleting paths until at least bytes bytes have been deleted,
    then stop. The argument bytes can be followed by the
    multiplicative suffix K, M, G or T, denoting KiB, MiB, GiB
    or TiB units.

{{#include ./opt-common.md}}

{{#include ./env-common.md}}

Example

To delete from the Nix store everything that is not used by the current
generations of each profile, do

console
$ nix-collect-garbage -d

Doc Manual Source Command Ref Nix Copy Closure (`doc/manual/source/command-ref/nix-copy-closure.md`)

Name

nix-copy-closure - copy store objects to or from a remote machine via SSH

Synopsis

nix-copy-closure
[--to | --from ]
[--gzip]
[--include-outputs]
[--use-substitutes | -s]
[-v]
[user@]machine[:port] paths

Description

Given paths from one machine, nix-copy-closure computes the closure of those paths (i.e. all their dependencies in the Nix store), and copies store objects in that closure to another machine via SSH.
It doesn’t copy store objects that are already present on the other machine.

Note

While the Nix store to use on the local machine can be specified on the command line with the --store option, the Nix store to be accessed on the remote machine can only be configured statically on that remote machine.

Since nix-copy-closure calls ssh, you may need to authenticate with the remote machine.
In fact, you may be asked for authentication twice because nix-copy-closure currently connects twice to the remote machine: first to get the set of paths missing on the target machine, and second to send the dump of those paths.
When using public key authentication, you can avoid typing the passphrase with ssh-agent.

Options

  • --to

    Copy the closure of paths from a Nix store accessible from the local machine to the Nix store on the remote machine.
    This is the default behavior.

  • --from

    Copy the closure of paths from the Nix store on the remote machine to the local machine's specified Nix store.

  • --gzip

    Enable compression of the SSH connection.

  • --include-outputs

    Also copy the outputs of store derivations included in the closure.

  • --use-substitutes / -s

    Attempt to download missing store objects on the target from substituters.
    Any store objects that cannot be substituted on the target are still copied normally from the source.
    This is useful, for instance, if the connection between the source and target machine is slow, but the connection between the target machine and cache.nixos.org (the default binary cache server) is fast.

{{#include ./opt-common.md}}

Environment variables

  • NIX_SSHOPTS

    Additional options to be passed to ssh on the command line.

{{#include ./env-common.md}}

Examples

Example

Copy GNU Hello with all its dependencies to a remote machine:

shell-session
$ storePath="$(nix-build '<nixpkgs>' -I nixpkgs=channel:nixpkgs-unstable -A hello --no-out-link)"
$ nix-copy-closure --to [email protected] "$storePath"
copying 5 paths...
copying path '/nix/store/h6q8sqsqfbd3252f9gixqn3z282wds7m-xgcc-13.2.0-libgcc' to 'ssh://[email protected]'...
copying path '/nix/store/imnwvn96lw355giswsk36hx105j4wnpj-libunistring-1.1' to 'ssh://[email protected]'...
copying path '/nix/store/85301indj7scg34spnfczkz72jgv8wa9-libidn2-2.3.7' to 'ssh://[email protected]'...
copying path '/nix/store/ypwfsaljwhzw9iffiysxmxnhjj8v7np0-glibc-2.39-31' to 'ssh://[email protected]'...
copying path '/nix/store/0dklv59zppdsqdvgf0qdvjgzcs5wbwxa-hello-2.12.1' to 'ssh://[email protected]'...

Example

Copy GNU Hello from a remote machine using a known store path, and run it:

shell-session
$ storePath="$(nix-instantiate --eval --raw '<nixpkgs>' -I nixpkgs=channel:nixpkgs-unstable -A hello.outPath)"
$ nix-copy-closure --from [email protected] "$storePath"
$ "$storePath"/bin/hello
Hello, world!

Doc Manual Source Command Ref Nix Daemon (`doc/manual/source/command-ref/nix-daemon.md`)

Name

nix-daemon - Nix multi-user support daemon

Synopsis

nix-daemon

Description

The Nix daemon is necessary in multi-user Nix installations. It runs
build tasks and other operations on the Nix store on behalf of
unprivileged users.


Doc Manual Source Command Ref Nix Env (`doc/manual/source/command-ref/nix-env.md`)

Name

nix-env - manipulate or query Nix user environments

Synopsis

nix-env operation [options] [arguments…]
[--option name value]
[--arg name value]
[--argstr name value]
[{--file | -f} path]
[{--profile | -p} path]
[--system-filter system]
[--dry-run]

Description

The command nix-env is used to manipulate Nix user environments. User
environments are sets of software packages available to a user at some
point in time. In other words, they are a synthesised view of the
programs available in the Nix store. There may be many user
environments: different users can have different environments, and
individual users can switch between different environments.

nix-env takes exactly one operation flag which indicates the
subcommand to be performed. The following operations are available:

These pages can be viewed offline:

  • man nix-env-<operation>.

    Example: man nix-env-install

  • nix-env --help --<operation>

    Example: nix-env --help --install

Package sources

nix-env can obtain packages from multiple sources:

  • An attribute set of derivations from:
    • The default Nix expression (by default)
    • A Nix file, specified via --file
    • A profile, specified via --from-profile
    • A Nix expression that is a function which takes default expression as argument, specified via --from-expression
  • A store path

Selectors

Several operations, such as nix-env --query and nix-env --install, take a list of arguments that specify the packages on which to operate.

Packages are identified based on a name part and a version part of a symbolic derivation name:

  • name: Everything up to but not including the first dash (-) that is not followed by a letter.
  • version: The rest, excluding the separating dash.

Example

nix-env parses the symbolic derivation name apache-httpd-2.0.48 as:

json
{
  "name": "apache-httpd",
  "version": "2.0.48"
}

Example

nix-env parses the symbolic derivation name firefox.* as:

json
{
  "name": "firefox.*",
  "version": ""
}

The name parts of the arguments to nix-env are treated as extended regular expressions and matched against the name parts of derivation names in the package source.
The match is case-sensitive.
The regular expression can optionally be followed by a dash (-) and a version number; if omitted, any version of the package will match.
For details on regular expressions, see regex(7).

Example

Common patterns for finding package names with nix-env:

  • firefox

    Matches the package name firefox and any version.

  • firefox-32.0

    Matches the package name firefox and version 32.0.

  • gtk\\+

    Matches the package name gtk+.
    The + character must be escaped using a backslash (\) to prevent it from being interpreted as a quantifier, and the backslash must be escaped in turn with another backslash to ensure that the shell passes it on.

  • .\*

    Matches any package name.
    This is the default for most commands.

  • '.*zip.*'

    Matches any package name containing the string zip.
    Note the dots: '*zip*' does not work, because in a regular expression, the character * is interpreted as a quantifier.

  • '.*(firefox|chromium).*'

    Matches any package name containing the strings firefox or chromium.

Files

nix-env operates on the following files.

{{#include ./files/default-nix-expression.md}}

{{#include ./files/profiles.md}}


Doc Manual Source Command Ref Nix Hash (`doc/manual/source/command-ref/nix-hash.md`)

Name

nix-hash - compute the cryptographic hash of a path

Synopsis

nix-hash [--flat] [--base32] [--truncate] [--type hashAlgo] path…

nix-hash [--to-base16|--to-base32|--to-base64|--to-sri] [--type hashAlgo] hash…

Description

The command nix-hash computes the cryptographic hash of the contents
of each path and prints it on standard output. By default, it computes
an MD5 hash, but other hash algorithms are available as well. The hash
is printed in hexadecimal. To generate the same hash as
nix-prefetch-url you have to specify multiple arguments, see below for
an example.

The hash is computed over a serialisation of each path: a dump of
the file system tree rooted at the path. This allows directories and
symlinks to be hashed as well as regular files. The dump is in the
Nix Archive (NAR) format produced by nix-store --dump. Thus, nix-hash path
yields the same cryptographic hash as nix-store --dump path | md5sum.

Options

  • --flat

    Print the cryptographic hash of the contents of each regular file path.
    That is, instead of computing
    the hash of the Nix Archive (NAR) of path,
    just directly hash path as is.
    This requires path to resolve to a regular file rather than directory.
    The result is identical to that produced by the GNU commands
    md5sum and sha1sum.

  • --base16

    Print the hash in a hexadecimal representation (default).

  • --base32

    Print the hash in Nix32 representation rather than hexadecimal.
    This representation is more compact and can be used in Nix
    expressions (such as in calls to fetchurl).

  • --base64

    Similar to --base32, but print the hash in a Base64 representation,
    which is more compact than the Nix32 one.

  • --sri

    Print the hash in SRI format with Base64 encoding.
    The type of hash algorithm will be prepended to the hash string,
    followed by a hyphen (-) and the Base64 hash body.

  • --truncate

    Truncate hashes longer than 160 bits (such as SHA-256) to 160 bits.

  • --type hashAlgo

    Use the specified cryptographic hash algorithm, which can be one of
    blake3, md5, sha1, sha256, and sha512.

  • --to-base16

    Don’t hash anything, but convert the Nix32 hash representation
    hash to hexadecimal.

  • --to-base32

    Don’t hash anything, but convert the hexadecimal hash representation
    hash to Nix32.

  • --to-base64

    Don’t hash anything, but convert the hexadecimal hash representation
    hash to Base64.

  • --to-sri

    Don’t hash anything, but convert the hexadecimal hash representation
    hash to SRI.

Examples

Computing the same hash as nix-prefetch-url:

console
$ nix-prefetch-url file://<(echo test)
1lkgqb6fclns49861dwk9rzb6xnfkxbpws74mxnx01z9qyv1pjpj
$ nix-hash --type sha256 --flat --base32 <(echo test)
1lkgqb6fclns49861dwk9rzb6xnfkxbpws74mxnx01z9qyv1pjpj

Computing hashes:

console
$ mkdir test
$ echo "hello" > test/world

$ nix-hash test/ (MD5 hash; default)
8179d3caeff1869b5ba1744e5a245c04

$ nix-store --dump test/ | md5sum (for comparison)
8179d3caeff1869b5ba1744e5a245c04  -

$ nix-hash --type sha1 test/
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6

$ nix-hash --type sha1 --base16 test/
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6

$ nix-hash --type sha1 --base32 test/
nvd61k9nalji1zl9rrdfmsmvyyjqpzg4

$ nix-hash --type sha1 --base64 test/
5P2Lpfe76upazon+ECVVNs1g2rY=

$ nix-hash --type sha1 --sri test/
sha1-5P2Lpfe76upazon+ECVVNs1g2rY=

$ nix-hash --type sha256 --flat test/
error: reading file `test/': Is a directory

$ nix-hash --type sha256 --flat test/world
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03

Converting between hexadecimal, Nix32, Base64, and SRI:

console
$ nix-hash --type sha1 --to-base32 e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
nvd61k9nalji1zl9rrdfmsmvyyjqpzg4

$ nix-hash --type sha1 --to-base16 nvd61k9nalji1zl9rrdfmsmvyyjqpzg4
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6

$ nix-hash --type sha1 --to-base64 e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
5P2Lpfe76upazon+ECVVNs1g2rY=

$ nix-hash --type sha1 --to-sri nvd61k9nalji1zl9rrdfmsmvyyjqpzg4
sha1-5P2Lpfe76upazon+ECVVNs1g2rY=

$ nix-hash --to-base16 sha1-5P2Lpfe76upazon+ECVVNs1g2rY=
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6

Doc Manual Source Command Ref Nix Instantiate (`doc/manual/source/command-ref/nix-instantiate.md`)

Name

nix-instantiate - instantiate store derivations from Nix expressions

Synopsis

nix-instantiate
[--parse | --eval [--strict] [--raw | --json | --xml] ]
[--read-write-mode]
[--arg name value]
[{--attr| -A} attrPath]
[--add-root path]
[--expr | -E]
files…

nix-instantiate --find-file files…

Description

The command nix-instantiate produces store derivations from (high-level) Nix expressions.
It evaluates the Nix expressions in each of files (which defaults to
./default.nix). Each top-level expression should evaluate to a
derivation, a list of derivations, or a set of derivations. The paths
of the resulting store derivations are printed on standard output.

If files is the character -, then a Nix expression will be read from
standard input.

Options

  • --add-root path

    See the corresponding option in nix-store.

  • --parse

    Just parse the input files, and print their abstract syntax trees on
    standard output as a Nix expression.

  • --eval

    Just parse and evaluate the input files, and print the resulting
    values on standard output.
    Store derivations are not serialized and written to the store, but instead just hashed and discarded.

    Warning

    This option produces output which can be parsed as a Nix expression which
    will produce a different result than the input expression when evaluated.
    For example, these two Nix expressions print the same result despite
    having different meaning:

    console
    $ nix-instantiate --eval --expr '{ a = {}; }'
    { a = <CODE>; }
    $ nix-instantiate --eval --expr '{ a = <CODE>; }'
    { a = <CODE>; }

    For human-readable output, nix eval (experimental) is more informative:

    console
    $ nix-instantiate --eval --expr 'a: a'
    <LAMBDA>
    $ nix eval --expr 'a: a'
    «lambda @ «string»:1:1»

    For machine-readable output, the --xml option produces unambiguous
    output:

    console
    $ nix-instantiate --eval --xml --expr '{ foo = <CODE>; }'
    <?xml version='1.0' encoding='utf-8'?>
    <expr>
      <attrs>
        <attr column="3" line="1" name="foo">
          <unevaluated />
        </attr>
      </attrs>
    </expr>
  • --find-file

    Look up the given files in Nix’s search path (as specified by the
    NIX_PATH environment variable). If found, print the corresponding
    absolute paths on standard output. For instance, if NIX_PATH is
    nixpkgs=/home/alice/nixpkgs, then nix-instantiate --find-file nixpkgs/default.nix will print /home/alice/nixpkgs/default.nix.

  • --strict

    When used with --eval, recursively evaluate list elements and
    attributes. Normally, such sub-expressions are left unevaluated
    (since the Nix language is lazy).

    Warning

    This option can cause non-termination, because lazy data
    structures can be infinitely large.

  • --raw

    When used with --eval, the evaluation result must be a string,
    which is printed verbatim, without quoting, escaping or trailing newline.

  • --json

    When used with --eval, print the resulting value as an JSON
    representation of the abstract syntax tree rather than as a Nix expression.

  • --xml

    When used with --eval, print the resulting value as an XML
    representation of the abstract syntax tree rather than as a Nix expression.
    The schema is the same as that used by the toXML
    built-in
    .

  • --read-write-mode

    When used with --eval, perform evaluation in read/write mode so
    nix language features that require it will still work (at the cost
    of needing to do instantiation of every evaluated derivation). If
    this option is not enabled, there may be uninstantiated store paths
    in the final output.

{{#include ./opt-common.md}}

{{#include ./env-common.md}}

Examples

Instantiate store derivations from a Nix expression, and build them using nix-store:

console
$ nix-instantiate test.nix (instantiate)
/nix/store/cigxbmvy6dzix98dxxh9b6shg7ar5bvs-perl-BerkeleyDB-0.26.drv

$ nix-store --realise $(nix-instantiate test.nix) (build)
...
/nix/store/qhqk4n8ci095g3sdp93x7rgwyh9rdvgk-perl-BerkeleyDB-0.26 (output path)

$ ls -l /nix/store/qhqk4n8ci095g3sdp93x7rgwyh9rdvgk-perl-BerkeleyDB-0.26
dr-xr-xr-x    2 eelco    users        4096 1970-01-01 01:00 lib
...

You can also give a Nix expression on the command line:

console
$ nix-instantiate --expr 'with import <nixpkgs> { }; hello'
/nix/store/j8s4zyv75a724q38cb0r87rlczaiag4y-hello-2.8.drv

This is equivalent to:

console
$ nix-instantiate '<nixpkgs>' --attr hello

Parsing and evaluating Nix expressions:

console
$ nix-instantiate --parse --expr '1 + 2'
1 + 2
console
$ nix-instantiate --eval --expr '1 + 2'
3
console
$ nix-instantiate --eval --xml --expr '1 + 2'
<?xml version='1.0' encoding='utf-8'?>
<expr>
  <int value="3" />
</expr>

The difference between non-strict and strict evaluation:

console
$ nix-instantiate --eval --xml --expr '{ x = {}; }'
<?xml version='1.0' encoding='utf-8'?>
<expr>
  <attrs>
    <attr column="3" line="1" name="x">
      <unevaluated />
    </attr>
  </attrs>
</expr>

$ nix-instantiate --eval --xml --strict --expr '{ x = {}; }'
<?xml version='1.0' encoding='utf-8'?>
<expr>
  <attrs>
    <attr column="3" line="1" name="x">
      <attrs>
      </attrs>
    </attr>
  </attrs>
</expr>

Doc Manual Source Command Ref Nix Prefetch Url (`doc/manual/source/command-ref/nix-prefetch-url.md`)

Name

nix-prefetch-url - copy a file from a URL into the store and print its hash

Synopsis

nix-prefetch-url url [hash]
[--type hashAlgo]
[--print-path]
[--unpack]
[--name name]

Description

The command nix-prefetch-url downloads the file referenced by the URL
url, prints its cryptographic hash, and copies it into the Nix store.
The file name in the store is hash-baseName, where baseName is
everything following the final slash in url.

This command is just a convenience for Nix expression writers. Often a
Nix expression fetches some source distribution from the network using
the fetchurl expression contained in Nixpkgs. However, fetchurl
requires a cryptographic hash. If you don't know the hash, you would
have to download the file first, and then fetchurl would download it
again when you build your Nix expression. Since fetchurl uses the same
name for the downloaded file as nix-prefetch-url, the redundant
download can be avoided.

If hash is specified, then a download is not performed if the Nix
store already contains a file with the same hash and base name.
Otherwise, the file is downloaded, and an error is signaled if the
actual hash of the file does not match the specified hash.

This command prints the hash on standard output.
The hash is printed using Nix32 unless --type md5 is specified,
in which case it's printed using base-16.
Additionally, if the option --print-path is used,
the path of the downloaded file in the Nix store is also printed.

Options

  • --type hashAlgo

    Use the specified cryptographic hash algorithm,
    which can be one of blake3, md5, sha1, sha256, and sha512.
    The default is sha256.

  • --print-path

    Print the store path of the downloaded file on standard output.

  • --unpack

    Unpack the archive (which must be a tarball or zip file) and add the
    result to the Nix store. The resulting hash can be used with
    functions such as Nixpkgs’s fetchzip or fetchFromGitHub.

  • --executable

    Set the executable bit on the downloaded file.

  • --name name

    Override the name of the file in the Nix store. By default, this is
    hash-basename, where basename is the last component of url.
    Overriding the name is necessary when basename contains characters
    that are not allowed in Nix store paths.

Examples

console
$ nix-prefetch-url ftp://ftp.gnu.org/pub/gnu/hello/hello-2.10.tar.gz
0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i
console
$ nix-prefetch-url --print-path mirror://gnu/hello/hello-2.10.tar.gz
0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i
/nix/store/8alrpdaasjd1x6g1fczchmzbpqm936a3-hello-2.10.tar.gz
console
$ nix-prefetch-url --unpack --print-path https://github.com/NixOS/patchelf/archive/0.8.tar.gz
079agjlv0hrv7fxnx9ngipx14gyncbkllxrp9cccnh3a50fxcmy7
/nix/store/19zrmhm3m40xxaw81c8cqm6aljgrnwj2-0.8.tar.gz

Doc Manual Source Command Ref Nix Shell (`doc/manual/source/command-ref/nix-shell.md`)

Name

nix-shell - start an interactive shell based on a Nix expression

Synopsis

nix-shell
[--arg name value]
[--argstr name value]
[{--attr | -A} attrPath]
[--command cmd]
[--run cmd]
[--exclude regexp]
[--pure]
[--keep name]
{{--packages | -p} {packages | expressions} … | [path]}

Disambiguation

This man page describes the command nix-shell, which is distinct from nix shell. For documentation on the latter, run nix shell --help or see man nix3-env-shell.

Description

The command nix-shell will build the dependencies of the specified
derivation, but not the derivation itself. It will then start an
interactive shell in which all environment variables defined by the
derivation path have been set to their corresponding values, and the
script $stdenv/setup has been sourced. This is useful for reproducing
the environment of a derivation for development.

If path is not given, nix-shell defaults to shell.nix if it
exists, and default.nix otherwise.

If path starts with http:// or https://, it is interpreted as the
URL of a tarball that will be downloaded and unpacked to a temporary
location. The tarball must include a single top-level directory
containing at least a file named default.nix.

If the derivation defines the variable shellHook, it will be run
after $stdenv/setup has been sourced. Since this hook is not executed
by regular Nix builds, it allows you to perform initialisation specific
to nix-shell. For example, the derivation attribute

nix
shellHook =
  ''
    echo "Hello shell"
    export SOME_API_TOKEN="$(cat ~/.config/some-app/api-token)"
  '';

will cause nix-shell to print Hello shell and set the SOME_API_TOKEN
environment variable to a user-configured value.

Options

All options not listed here are passed to nix-store --realise, except for --arg and --attr / -A which are passed to
nix-instantiate.

  • --command cmd

    In the environment of the derivation, run the shell command cmd.
    This command is executed in an interactive shell. (Use --run to
    use a non-interactive shell instead.) However, a call to exit is
    implicitly added to the command, so the shell will exit after
    running the command. To prevent this, add return at the end;
    e.g. --command "echo Hello; return" will print Hello and then
    drop you into the interactive shell. This can be useful for doing
    any additional initialisation.

  • --run cmd

    Like --command, but executes the command in a non-interactive
    shell. This means (among other things) that if you hit Ctrl-C while
    the command is running, the shell exits.

  • --exclude regexp

    Do not build any dependencies whose store path matches the regular
    expression regexp. This option may be specified multiple times.

  • --pure

    If this flag is specified, the environment is almost entirely
    cleared before the interactive shell is started, so you get an
    environment that more closely corresponds to the “real” Nix build. A
    few variables, in particular HOME, USER and DISPLAY, are
    retained. Note that the shell used to run commands is obtained from
    NIX_BUILD_SHELL / <nixpkgs> from
    NIX_PATH, and therefore not affected by --pure.

  • --packages / -p packages…

    Set up an environment in which the specified packages are present.
    The command line arguments are interpreted as attribute names inside
    the Nix Packages collection. Thus, nix-shell --packages libjpeg openjdk
    will start a shell in which the packages denoted by the attribute
    names libjpeg and openjdk are present.

  • -i interpreter

    The chained script interpreter to be invoked by nix-shell. Only
    applicable in #!-scripts (described below).

  • --keep name

    When a --pure shell is started, keep the listed environment
    variables.

{{#include ./opt-common.md}}

Environment variables

  • NIX_BUILD_SHELL

    Shell used to start the interactive environment.
    Defaults to the bash from bashInteractive found in <nixpkgs>, falling back to the bash found in PATH if not found.

    Note

    The shell obtained using this method may not necessarily be the same as any shells requested in path.

    **Example

    Despite --pure, this invocation will not result in a fully reproducible shell environment:

    nix
    #!/usr/bin/env -S nix-shell --pure
    let
      pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/854fdc68881791812eddd33b2fed94b954979a8e.tar.gz") {};
    in
    pkgs.mkShell {
      buildInputs = pkgs.bashInteractive;
    }

{{#include ./env-common.md}}

Examples

To build the dependencies of the package Pan, and start an interactive
shell in which to build it:

console
$ nix-shell '<nixpkgs>' --attr pan
[nix-shell]$ eval ${unpackPhase:-unpackPhase}
[nix-shell]$ cd $sourceRoot
[nix-shell]$ eval ${patchPhase:-patchPhase}
[nix-shell]$ eval ${configurePhase:-configurePhase}
[nix-shell]$ eval ${buildPhase:-buildPhase}
[nix-shell]$ ./pan/gui/pan

The reason we use form eval ${configurePhase:-configurePhase} here is because
those packages that override these phases do so by exporting the overridden
values in the environment variable of the same name.
Here bash is being told to either evaluate the contents of 'configurePhase',
if it exists as a variable, otherwise evaluate the configurePhase function.

To clear the environment first, and do some additional automatic
initialisation of the interactive shell:

console
$ nix-shell '<nixpkgs>' --attr pan --pure \
    --command 'export NIX_DEBUG=1; export NIX_CORES=8; return'

Nix expressions can also be given on the command line using the -E and
-p flags. For instance, the following starts a shell containing the
packages sqlite and libX11:

console
$ nix-shell --expr 'with import <nixpkgs> { }; runCommand "dummy" { buildInputs = [ sqlite xorg.libX11 ]; } ""'

A shorter way to do the same is:

console
$ nix-shell --packages sqlite xorg.libX11
[nix-shell]$ echo $NIX_LDFLAGS
… -L/nix/store/j1zg5v…-sqlite-3.8.0.2/lib -L/nix/store/0gmcz9…-libX11-1.6.1/lib …

Note that -p accepts multiple full nix expressions that are valid in
the buildInputs = [ ... ] shown above, not only package names. So the
following is also legal:

console
$ nix-shell --packages sqlite 'git.override { withManual = false; }'

The -p flag looks up Nixpkgs in the Nix search path. You can override
it by passing -I or setting NIX_PATH. For example, the following
gives you a shell containing the Pan package from a specific revision of
Nixpkgs:

console
$ nix-shell --packages pan -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/8a3eea054838b55aca962c3fbde9c83c102b8bf2.tar.gz

[nix-shell:~]$ pan --version
Pan 0.139

Use as a `#!`-interpreter

You can use nix-shell as a script interpreter to allow scripts written
in arbitrary languages to obtain their own dependencies via Nix. This is
done by starting the script with the following lines:

bash
#! /usr/bin/env nix-shell
#! nix-shell -i real-interpreter --packages packages

where real-interpreter is the “real” script interpreter that will be
invoked by nix-shell after it has obtained the dependencies and
initialised the environment, and packages are the attribute names of
the dependencies in Nixpkgs.

The lines starting with #! nix-shell specify nix-shell options (see
above). Note that you cannot write #! /usr/bin/env nix-shell -i ...
because many operating systems only allow one argument in #! lines.

For example, here is a Python script that depends on Python and the
prettytable package:

python
#! /usr/bin/env nix-shell
#! nix-shell -i python3 --packages python3 python3Packages.prettytable

import prettytable

# Print a simple table.
t = prettytable.PrettyTable(["N", "N^2"])
for n in range(1, 10): t.add_row([n, n * n])
print(t)

Similarly, the following is a Perl script that specifies that it
requires Perl and the HTML::TokeParser::Simple, LWP and
LWP::Protocol::Https packages:

perl
#! /usr/bin/env nix-shell
#! nix-shell -i perl 
#! nix-shell --packages perl 
#! nix-shell --packages perlPackages.HTMLTokeParserSimple 
#! nix-shell --packages perlPackages.LWP
#! nix-shell --packages perlPackages.LWPProtocolHttps

use HTML::TokeParser::Simple;

# Fetch nixos.org and print all hrefs.
my $p = HTML::TokeParser::Simple->new(url => 'https://nixos.org/');

while (my $token = $p->get_tag("a")) {
    my $href = $token->get_attr("href");
    print "$href\n" if $href;
}

Sometimes you need to pass a simple Nix expression to customize a
package like Terraform:

bash
#! /usr/bin/env nix-shell
#! nix-shell -i bash --packages 'terraform.withPlugins (plugins: [ plugins.openstack ])'

terraform apply

Note

You must use single or double quotes (', ") when passing a simple Nix expression
in a nix-shell shebang.

Finally, using the merging of multiple nix-shell shebangs the following
Haskell script uses a specific branch of Nixpkgs/NixOS (the 20.03 stable
branch):

haskell
#! /usr/bin/env nix-shell
#! nix-shell -i runghc --packages 'haskellPackages.ghcWithPackages (ps: [ps.download-curl ps.tagsoup])'
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/nixos-20.03.tar.gz

import Network.Curl.Download
import Text.HTML.TagSoup
import Data.Either
import Data.ByteString.Char8 (unpack)

-- Fetch nixos.org and print all hrefs.
main = do
  resp <- openURI "https://nixos.org/"
  let tags = filter (isTagOpenName "a") $ parseTags $ unpack $ fromRight undefined resp
  let tags' = map (fromAttrib "href") tags
  mapM_ putStrLn $ filter (/= "") tags'

If you want to be even more precise, you can specify a specific revision
of Nixpkgs:

text
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/0672315759b3e15e2121365f067c1c8c56bb4722.tar.gz

The examples above all used -p to get dependencies from Nixpkgs. You
can also use a Nix expression to build your own dependencies. For
example, the Python example could have been written as:

python
#! /usr/bin/env nix-shell
#! nix-shell deps.nix -i python

where the file deps.nix in the same directory as the #!-script
contains:

nix
with import <nixpkgs> {};

runCommand "dummy" { buildInputs = [ python3 python3Packages.prettytable ]; } ""

The script's file name is passed as the first argument to the interpreter specified by the -i flag.

Aside from the very first line, which is a directive to the operating system, the additional #! nix-shell lines do not need to be at the beginning of the file.
This allows wrapping them in block comments for languages where # does not start a comment, such as ECMAScript, Erlang, or PHP.


Doc Manual Source Command Ref Nix Store (`doc/manual/source/command-ref/nix-store.md`)

Name

nix-store - manipulate or query the Nix store

Synopsis

nix-store operation [options…] [arguments…]
[--option name value]
[--add-root path]

Description

The command nix-store performs primitive operations on the Nix store.
You generally do not need to run this command manually.

nix-store takes exactly one operation flag which indicates the subcommand to be performed. The following operations are available:

These pages can be viewed offline:

  • man nix-store-<operation>.

    Example: man nix-store-realise

  • nix-store --help --<operation>

    Example: nix-store --help --realise


Doc Manual Source Command Ref Opt Common (`doc/manual/source/command-ref/opt-common.md`)

Common Options

Most Nix commands accept the following command-line options:

  • --help

    Prints out a summary of the command syntax and exits.

  • --version

    Prints out the Nix version number on standard output and exits.

    For machine-readable output, including versions of the libraries Nix
    links against, see the nix version command.

  • --verbose / -v

    Increases the level of verbosity of diagnostic messages printed on standard error.
    For each Nix operation, the information printed on standard output is well-defined;
    any diagnostic information is printed on standard error, never on standard output.

    This option may be specified repeatedly.
    Currently, the following verbosity levels exist:

    • 0 “Errors only”

      Only print messages explaining why the Nix invocation failed.

    • 1 “Informational”

      Print useful messages about what Nix is doing.
      This is the default.

    • 2 “Talkative”

      Print more informational messages.

    • 3 “Chatty”

      Print even more informational messages.

    • 4 “Debug”

      Print debug information.

    • 5 “Vomit”

      Print vast amounts of debug information.

  • --quiet

    Decreases the level of verbosity of diagnostic messages printed on standard error.
    This is the inverse option to -v / --verbose.

    This option may be specified repeatedly.
    See the previous verbosity levels list.

  • --log-format format

    This option can be used to change the output of the log format, with format being one of:

    • raw

      This is the raw format, as outputted by nix-build.

    • internal-json

      Outputs the logs in a structured manner.

      Warning

      While the schema itself is relatively stable, the format of
      the error-messages (namely of the msg-field) can change
      between releases.

    • bar

      Only display a progress bar during the builds.

    • bar-with-logs

      Display the raw logs, with the progress bar at the bottom.

  • --no-build-output / -Q

    By default, output written by builders to standard output and standard error is echoed to the Nix command's standard error.
    This option suppresses this behaviour.
    Note that the builder's standard output and error are always written to a log file in prefix/nix/var/log/nix.

  • --max-jobs / -j number

    Sets the maximum number of build jobs that Nix will perform in parallel to the specified number.
    Specify auto to use the number of CPUs in the system.
    The default is specified by the max-jobs configuration setting, which itself defaults to 1.
    A higher value is useful on SMP systems or to exploit I/O latency.

    Setting it to 0 disallows building on the local machine, which is useful when you want builds to happen only on remote builders.

  • --cores

    Sets the value of the NIX_BUILD_CORES environment variable in the invocation of builders.
    Builders can use this variable at their discretion to control the maximum amount of parallelism.
    For instance, in Nixpkgs, if the derivation attribute enableParallelBuilding is set to true, the builder passes the -jN flag to GNU Make.
    It defaults to the value of the cores configuration setting, if set, or 1 otherwise.
    The value 0 means that the builder should use all available CPU cores in the system.

  • --max-silent-time

    Sets the maximum number of seconds that a builder can go without producing any data on standard output or standard error.
    The default is specified by the max-silent-time configuration setting.
    0 means no time-out.

  • --timeout

    Sets the maximum number of seconds that a builder can run.
    The default is specified by the timeout configuration setting.
    0 means no timeout.

  • --keep-going / -k

    Keep going in case of failed builds, to the greatest extent possible.
    That is, if building an input of some derivation fails, Nix will still build the other inputs, but not the derivation itself.
    Without this option, Nix stops if any build fails (except for builds of substitutes), possibly killing builds in progress (in case of parallel or distributed builds).

  • --keep-failed / -K

    Specifies that in case of a build failure, the temporary directory (usually in /tmp) in which the build takes place should not be deleted.
    The path of the build directory is printed as an informational message.

  • --fallback

    Whenever Nix attempts to build a derivation for which substitutes are known for each output path, but realising the output paths through the substitutes fails, fall back on building the derivation.

    The most common scenario in which this is useful is when we have registered substitutes in order to perform binary distribution from, say, a network repository.
    If the repository is down, the realisation of the derivation will fail.
    When this option is specified, Nix will build the derivation instead.
    Thus, installation from binaries falls back on installation from source.
    This option is not the default since it is generally not desirable for a transient failure in obtaining the substitutes to lead to a full build from source (with the related consumption of resources).

  • --readonly-mode

    When this option is used, no attempt is made to open the Nix database.
    Most Nix operations do need database access, so those operations will fail.

  • --arg name value

    This option is accepted by nix-env, nix-instantiate, nix-shell and nix-build.
    When evaluating Nix expressions, the expression evaluator will automatically try to call functions that it encounters.
    It can automatically call functions for which every argument has a default value (e.g., { argName ? defaultValue }: ...).

    With --arg, you can also call functions that have arguments without a default value (or override a default value).
    That is, if the evaluator encounters a function with an argument named name, it will call it with value value.

    For instance, the top-level default.nix in Nixpkgs is actually a function:

    nix
    { # The system (e.g., `i686-linux') for which to build the packages.
      system ? builtins.currentSystem
      ...
    }: ...

    So if you call this Nix expression (e.g., when you do nix-env --install --attr pkgname), the function will be called automatically using the value builtins.currentSystem for the system argument.
    You can override this using --arg, e.g., nix-env --install --attr pkgname --arg system \"i686-freebsd\".
    (Note that since the argument is a Nix string literal, you have to escape the quotes.)

  • --arg-from-file name path

    Pass the contents of file path as the argument name to Nix functions.

  • --arg-from-stdin name

    Pass the contents of stdin as the argument name to Nix functions.

  • --argstr name value

    This option is like --arg, only the value is not a Nix expression but a string.
    So instead of --arg system \"i686-linux\" (the outer quotes are to keep the shell happy) you can say --argstr system i686-linux.

  • --attr / -A attrPath

    Select an attribute from the top-level Nix expression being evaluated.
    (nix-env, nix-instantiate, nix-build and nix-shell only.)
    The attribute path attrPath is a sequence of attribute names separated by dots.
    For instance, given a top-level Nix expression e, the attribute path xorg.xorgserver would cause the expression e.xorg.xorgserver to be used.
    See nix-env --install for some concrete examples.

    In addition to attribute names, you can also specify array indices.
    For instance, the attribute path foo.3.bar selects the bar
    attribute of the fourth element of the array in the foo attribute
    of the top-level expression.

  • --eval-store store-url

    The URL to the Nix store to use for evaluation, i.e. where to store derivations (.drv files) and inputs referenced by them.

  • --expr / -E

    Interpret the command line arguments as a list of Nix expressions to be parsed and evaluated, rather than as a list of file names of Nix expressions.
    (nix-instantiate, nix-build and nix-shell only.)

    For nix-shell, this option is commonly used to give you a shell in which you can build the packages returned by the expression.
    If you want to get a shell which contain the built packages ready for use, give your expression to the nix-shell --packages convenience flag instead.

  • -I / --include path

    Add an entry to the list of search paths used to resolve lookup paths.
    This option may be given multiple times.

    Paths added through -I take precedence over the nix-path configuration setting and the NIX_PATH environment variable.

  • --impure

    Allow access to mutable paths and repositories.

  • --option name value

    Set the Nix configuration option name to value.
    This overrides settings in the Nix configuration file (see nix.conf5).

  • --repair

    Fix corrupted or missing store paths by redownloading or rebuilding them.
    Note that this is slow because it requires computing a cryptographic hash of the contents of every path in the closure of the build.
    Also note the warning under nix-store --repair-path.

Note

See man nix.conf for overriding configuration settings with command line flags.


Doc Manual Source Command Ref Status Build Failure (`doc/manual/source/command-ref/status-build-failure.md`)

Special exit codes for build failure

1xx status codes are used when requested builds failed.
The following codes are in use:

  • 100 Generic build failure

    The builder process returned with a non-zero exit code.

  • 101 Build timeout

    The build was aborted because it did not complete within the specified timeout.

  • 102 Hash mismatch

    The build output was rejected because it does not match the
    outputHash attribute of the derivation.

  • 104 Not deterministic

    The build succeeded in check mode but the resulting output is not binary reproducible.

With the --keep-going flag it's possible for multiple failures to occur.
In this case the 1xx status codes are or combined using
bitwise OR.

text
0b1100100
     ^^^^
     |||`- timeout
     ||`-- output hash mismatch
     |`--- build failure
     `---- not deterministic

Doc Manual Source Command Ref Utilities (`doc/manual/source/command-ref/utilities.md`)

Utilities

This section lists utilities that you can use when you work with Nix.


Doc Manual Source Development Benchmarking (`doc/manual/source/development/benchmarking.md`)

Running Benchmarks

This guide explains how to build and run performance benchmarks in the Nix codebase.

Overview

Nix uses the Google Benchmark framework for performance testing. Benchmarks help measure and track the performance of critical operations like derivation parsing.

Building Benchmarks

Benchmarks are disabled by default and must be explicitly enabled during the build configuration. For accurate results, use a debug-optimized release build.

Development Environment Setup

First, enter the development shell which includes the necessary dependencies:

bash
nix develop .#native-ccacheStdenv

Configure Build with Benchmarks

From the project root, configure the build with benchmarks enabled and optimization:

bash
cd build
meson configure -Dbenchmarks=true -Dbuildtype=debugoptimized

The debugoptimized build type provides:

  • Compiler optimizations for realistic performance measurements
  • Debug symbols for profiling and analysis
  • Balance between performance and debuggability

Build the Benchmarks

Build the project including benchmarks:

bash
ninja

This will create benchmark executables in the build directory. Currently available:

  • build/src/libstore-tests/nix-store-benchmarks - Store-related performance benchmarks

Additional benchmark executables will be created as more benchmarks are added to the codebase.

Running Benchmarks

Basic Usage

Run benchmark executables directly. For example, to run store benchmarks:

bash
./build/src/libstore-tests/nix-store-benchmarks

As more benchmark executables are added, run them similarly from their respective build directories.

Filtering Benchmarks

Run specific benchmarks using regex patterns:

bash
# Run only derivation parser benchmarks
./build/src/libstore-tests/nix-store-benchmarks --benchmark_filter="derivation.*"

# Run only benchmarks for hello.drv
./build/src/libstore-tests/nix-store-benchmarks --benchmark_filter=".*hello.*"

Output Formats

Generate benchmark results in different formats:

bash
# JSON output
./build/src/libstore-tests/nix-store-benchmarks --benchmark_format=json > results.json

# CSV output
./build/src/libstore-tests/nix-store-benchmarks --benchmark_format=csv > results.csv

Advanced Options

bash
# Run benchmarks multiple times for better statistics
./build/src/libstore-tests/nix-store-benchmarks --benchmark_repetitions=10

# Set minimum benchmark time (useful for micro-benchmarks)
./build/src/libstore-tests/nix-store-benchmarks --benchmark_min_time=2

# Compare against baseline
./build/src/libstore-tests/nix-store-benchmarks --benchmark_baseline=baseline.json

# Display time in custom units
./build/src/libstore-tests/nix-store-benchmarks --benchmark_time_unit=ms

Writing New Benchmarks

To add new benchmarks:

  1. Create a new .cc file in the appropriate *-tests directory

  2. Include the benchmark header:

    cpp
    #include <benchmark/benchmark.h>
  3. Write benchmark functions:

    cpp
    static void BM_YourBenchmark(benchmark::State & state)
    {
        // Setup code here
    
        for (auto _ : state) {
            // Code to benchmark
        }
    }
    BENCHMARK(BM_YourBenchmark);
  4. Add the file to the corresponding meson.build:

    meson
    benchmarks_sources = files(
        'your-benchmark.cc',
        # existing benchmarks...
    )

Profiling with Benchmarks

For deeper performance analysis, combine benchmarks with profiling tools:

bash
# Using Linux perf
perf record ./build/src/libstore-tests/nix-store-benchmarks
perf report

Using Valgrind Callgrind

Valgrind's callgrind tool provides detailed profiling information that can be visualized with kcachegrind:

bash
# Profile with callgrind
valgrind --tool=callgrind ./build/src/libstore-tests/nix-store-benchmarks

# Visualize the results with kcachegrind
kcachegrind callgrind.out.*

This provides:

  • Function call graphs
  • Instruction-level profiling
  • Source code annotation
  • Interactive visualization of performance bottlenecks

Continuous Performance Testing

bash
# Save baseline results
./build/src/libstore-tests/nix-store-benchmarks --benchmark_format=json > baseline.json

# Compare against baseline in CI
./build/src/libstore-tests/nix-store-benchmarks --benchmark_baseline=baseline.json

Troubleshooting

Benchmarks not building

Ensure benchmarks are enabled:

bash
meson configure build | grep benchmarks
# Should show: benchmarks true

Inconsistent results

  • Ensure your system is not under heavy load
  • Disable CPU frequency scaling for consistent results
  • Run benchmarks multiple times with --benchmark_repetitions

See Also


Doc Manual Source Development Building (`doc/manual/source/development/building.md`)

Building Nix

This section provides some notes on how to start hacking on Nix.
To get the latest version of Nix from GitHub:

Note

When checking out the repo on Windows, make sure you have the git setting core.symlinks enabled, before cloning, as there are symlinks in the repo.

console
$ git clone https://github.com/NixOS/nix.git
$ cd nix

Note

The following instructions assume you already have some version of Nix installed locally, so that you can use it to set up the development environment.
If you don't have it installed, follow the installation instructions.

To build all dependencies and start a shell in which all environment variables are set up so that those dependencies can be found:

console
$ nix-shell

To get a shell with one of the other supported compilation environments:

console
$ nix-shell --attr devShells.x86_64-linux.native-clangStdenv

Note

You can use native-ccacheStdenv to drastically improve rebuild time.
By default, ccache keeps artifacts in ~/.cache/ccache/.

To build Nix itself in this shell:

console
[nix-shell]$ out="$(pwd)/outputs/out" dev=$out debug=$out mesonFlags+=" --prefix=${out}"
[nix-shell]$ dontAddPrefix=1 configurePhase
[nix-shell]$ buildPhase

To test it:

console
[nix-shell]$ checkPhase

To install it in $(pwd)/outputs:

console
[nix-shell]$ installPhase
[nix-shell]$ ./outputs/out/bin/nix --version
nix (Nix) 2.12

To build a release version of Nix for the current operating system and CPU architecture:

console
$ nix-build

You can also build Nix for one of the supported platforms.

Building Nix with flakes

This section assumes you are using Nix with the flakes and nix-command experimental features enabled.

To build all dependencies and start a shell in which all environment variables are set up so that those dependencies can be found:

console
$ nix develop

This shell also adds ./outputs/bin/nix to your $PATH so you can run nix immediately after building it.

To get a shell with one of the other supported compilation environments:

console
$ nix develop .#native-clangStdenv

Note

Use ccacheStdenv to drastically improve rebuild time.
By default, ccache keeps artifacts in ~/.cache/ccache/.

To build Nix itself in this shell:

console
[nix-shell]$ configurePhase
[nix-shell]$ buildPhase

To test it:

console
[nix-shell]$ checkPhase

To install it in $(pwd)/outputs:

console
[nix-shell]$ installPhase
[nix-shell]$ nix --version
nix (Nix) 2.12

For more information on running and filtering tests, see
testing.md.

To build a release version of Nix for the current operating system and CPU architecture:

console
$ nix build

You can also build Nix for one of the supported platforms.

Platforms

Nix can be built for various platforms, as specified in flake.nix:

  • x86_64-linux
  • i686-linux
  • aarch64-linux
  • aarch64-darwin
  • armv6l-linux
  • armv7l-linux
  • powerpc64-linux (ELFv1 ABI)
  • powerpc64le-linux
  • riscv64-linux

In order to build Nix for a different platform than the one you're currently
on, you need a way for your current Nix installation to build code for that
platform. Common solutions include [remote build machines] and binary format emulation
(only supported on NixOS).

Given such a setup, executing the build only requires selecting the respective attribute.
For example, to compile for aarch64-linux:

console
$ nix-build --attr packages.aarch64-linux.default

or for Nix with the flakes and nix-command experimental features enabled:

console
$ nix build .#packages.aarch64-linux.default

Cross-compiled builds are available for:

  • armv6l-linux
  • armv7l-linux
  • powerpc64-linux (ELFv1 ABI)
  • powerpc64le-linux
  • riscv64-linux
    Add more system types to crossSystems in flake.nix to bootstrap Nix on unsupported platforms.

Building for multiple platforms at once

It is useful to perform multiple cross and native builds on the same source tree,
for example to ensure that better support for one platform doesn't break the build for another.
Meson thankfully makes this very easy by confining all build products to the build directory --- one simple shares the source directory between multiple build directories, each of which contains the build for Nix to a different platform.

Here's how to do that:

  1. Instruct Nixpkgs's infra where we want Meson to put its build directory

    bash
    mesonBuildDir=build-my-variant-name
  2. Configure as usual

    bash
    configurePhase
  3. Build as usual

    bash
    buildPhase

System type

Nix uses a string with the following format to identify the system type or platform it runs on:

text
<cpu>-<os>[-<abi>]

It is set when Nix is compiled for the given system, and based on the output of Meson's host_machine information.

For historic reasons and backward-compatibility, some CPU and OS identifiers are translated as follows:

host_machine.cpu_family() host_machine.endian() Nix
x86 i686
arm host_machine.cpu()
ppc little powerpcle
ppc64 little powerpc64le
ppc big powerpc
ppc64 big powerpc64
mips little mipsel
mips64 little mips64el
mips big mips
mips64 big mips64

When cross-compiling Nix with Meson for local development, you need to specify a cross-file using the --cross-file option. Cross-files define the target architecture and toolchain. When cross-compiling Nix with Nix, Nixpkgs takes care of this for you.

In the nix flake we also have some cross-compilation targets available:

text
nix build .#nix-everything-riscv64-unknown-linux-gnu
nix build .#nix-everything-armv7l-unknown-linux-gnueabihf
nix build .#nix-everything-armv7l-unknown-linux-gnueabihf
nix build .#nix-everything-x86_64-unknown-freebsd
nix build .#nix-everything-x86_64-w64-mingw32

Compilation environments

Nix can be compiled using multiple environments:

  • stdenv: default;
  • gccStdenv: force the use of gcc compiler;
  • clangStdenv: force the use of clang compiler;
  • ccacheStdenv: enable [ccache], a compiler cache to speed up compilation.

To build with one of those environments, you can use

console
$ nix build .#nix-cli-ccacheStdenv

for flake-enabled Nix, or

console
$ nix-build --attr nix-cli-ccacheStdenv

for classic Nix.

You can use any of the other supported environments in place of nix-cli-ccacheStdenv.

Editor integration

The clangd LSP server is installed by default on the clang-based devShells.
See supported compilation environments and instructions how to set up a shell with flakes or in classic Nix.

To use the LSP with your editor, you will want a compile_commands.json file telling clangd how we are compiling the code.
Meson's configure always produces this inside the build directory.

Configure your editor to use the clangd from the .#native-clangStdenv shell.
You can do that either by running it inside the development shell, or by using nix-direnv and the appropriate editor plugin.

Note

For some editors (e.g. Visual Studio Code), you may need to install a special extension for the editor to interact with clangd.
Some other editors (e.g. Emacs, Vim) need a plugin to support LSP servers in general (e.g. lsp-mode for Emacs and vim-lsp for vim).
Editor-specific setup is typically opinionated, so we will not cover it here in more detail.

Formatting and pre-commit hooks

You may run the formatters as a one-off using:

console
./maintainers/format.sh

Pre-commit hooks

If you'd like to run the formatters before every commit, install the hooks:

text
pre-commit-hooks-install

This installs pre-commit using cachix/git-hooks.nix.

When making a commit, pay attention to the console output.
If it fails, run git add --patch to approve the suggestions and commit again.

To refresh pre-commit hook's config file, do the following:

  1. Exit the development shell and start it again by running nix develop.
  2. If you also use the pre-commit hook, also run pre-commit-hooks-install again.

VSCode

Insert the following json into your .vscode/settings.json file to configure nixfmt.
This will be picked up by the Format Document command, "editor.formatOnSave", etc.

json
{
  "nix.formatterPath": "nixfmt",
  "nix.serverSettings": {
    "nixd": {
      "formatting": {
        "command": [
          "nixfmt"
        ],
      },
    },
    "nil": {
      "formatting": {
        "command": [
          "nixfmt"
        ],
      },
    },
  },
}

Doc Manual Source Development Cli Guideline (`doc/manual/source/development/cli-guideline.md`)

CLI guideline

Goals

Purpose of this document is to provide a clear direction to help design
delightful command line
experience. This document contains guidelines to
follow to ensure a consistent and approachable user experience.

Overview

nix command provides a single entry to a number of sub-commands that help
developers and system administrators in the life-cycle of a software
project. We particularly need to pay special attention to help and assist new
users of Nix.

Naming the `COMMANDS`

Words matter. Naming is an important part of the usability. Users will be
interacting with Nix on a regular basis so we should name things for ease of
understanding
.

We recommend following the Principle of Least
Astonishment
.
This means that you should never use acronyms or abbreviations unless they
are commonly used in other tools (e.g. nix init). And if the command name is
too long (> 10-12 characters) then shortening it makes sense (e.g.
“prioritization” → “priority”).

Commands should follow a noun-verb dialogue. Although noun-verb formatting
seems backwards from a speaking perspective (i.e. nix store copy vs. nix copy store) it allows us to organize commands the same way users think about
completing an action (the group first, then the command).

Naming rules

Rules are there to guide you by limiting your options. But not everything can
fit the rules all the time. In those cases document the exceptions in Appendix
1: Commands naming exceptions
and
provide reason. The rules want to force a Nix developer to look, not just at
the command at hand, but also the command in a full context alongside other
nix commands.

shell
$ nix [<GROUP>] <COMMAND> [<ARGUMENTS>] [<OPTIONS>]
  • GROUP, COMMAND, ARGUMENTS and OPTIONS should be lowercase and in a
    singular form.
  • GROUP should be a NOUN.
  • COMMAND should be a VERB.
  • ARGUMENTS and OPTIONS are discussed in Input section.

Classification

Some commands are more important, some less. While we want all of our commands
to be perfect we can only spend limited amount of time testing and improving
them.

This classification tries to separate commands in 3 categories in terms of
their importance in regards to the new users. Users who are likely to be
impacted the most by bad user experience.

  • Main commands

    Commands used for our main use cases and most likely used by new users. We
    expect attention to details, such as:

    Examples of such commands: nix init, nix develop, nix build, nix run,
    ...

  • Infrequently used commands

    From infrequently used commands we expect less attention to details, but
    still some:

    Examples of such commands: nix edit, nix eval, ...

  • Utility and scripting commands

    Commands that expose certain internal functionality of nix, mostly used by
    other scripts.

    Examples of such commands: nix store copy, nix hash base16, nix store ping, ...

Help is essential

Help should be built into your command line so that new users can gradually
discover new features when they need them.

Looking for help

Since there is no standard way how user will look for help we rely on ways help
is provided by commonly used tools. As a guide for this we took git and
whenever in doubt look at it as a preferred direction.

The rules are:

  • Help is shown by using --help or help command (eg nix --``help or
    nix help).
  • For non-COMMANDs (eg. nix --``help and nix store --``help) we show
    a summary
    of most common use cases. Summary is presented on the STDOUT
    without any use of PAGER.
  • For COMMANDs (eg. nix init --``help or nix help init) we display the
    man page of that command. By default the PAGER is used (as in git).
  • At the end of either summary or man page there should be an URL pointing to
    an online version of more detailed documentation.
  • The structure of summaries and man pages should be the same as in git.

Anticipate where help is needed

Even better then requiring the user to search for help is to anticipate and
predict when user might need it. Either because the lack of discoverability,
typo in the input or simply taking the opportunity to teach the user of
interesting - but less visible - details.

Shell completion

This type of help is most common and almost expected by users. We need to
provide the best shell completion for bash, zsh and fish.

Completion needs to be context aware, this mean when a user types:

shell
$ nix build n<TAB>

we need to display a list of flakes starting with n.

Wrong input

As we all know we humans make mistakes, all the time. When a typo - intentional
or unintentional - is made, we should prompt for closest possible options or
point to the documentation which would educate user to not make the same
errors. Here are few examples:

In first example we prompt the user for typing wrong command name:

shell
$ nix int
------------------------------------------------------------------------
  Error! Command `int` not found.
------------------------------------------------------------------------
  Did you mean:
    |> nix init
    |> nix input

Sometimes users will make mistake either because of a typo or simply because of
lack of discoverability. Our handling of this cases needs to be context
sensitive.

shell
$ nix init --template=template#python
------------------------------------------------------------------------
  Error! Template `template#python` not found.
------------------------------------------------------------------------
Initializing Nix project at `/path/to/here`.
      Select a template for you new project:
          |> template#python
             template#python-pip
             template#python-poetry

Next steps

It can be invaluable to newcomers to show what a possible next steps and what
is the usual development workflow with Nix. For example:

shell
$ nix init --template=template#python
Initializing project `template#python`
          in `/home/USER/dev/new-project`

  Next steps
    |> nix develop   -- to enter development environment
    |> nix build     -- to build your project

Educate the user

We should take any opportunity to educate users, but at the same time we
must be very very careful to not annoy users. There is a thin line between
being helpful and being annoying.

An example of educating users might be to provide Tips in places where they
are waiting.

shell
$ nix build
    Started building my-project 1.2.3
 Downloaded python3.8-poetry 1.2.3 in 5.3 seconds
 Downloaded python3.8-requests 1.2.3 in 5.3 seconds
------------------------------------------------------------------------
      Press `v` to increase logs verbosity
         |> `?` to see other options
------------------------------------------------------------------------
      Learn something new with every build...
         |> See last logs of a build with `nix log --last` command.
------------------------------------------------------------------------
  Evaluated my-project 1.2.3 in 14.43 seconds
Downloading [12 / 200]
         |> firefox 1.2.3 [#########>       ] 10Mb/s | 2min left
   Building [2 / 20]
         |> glibc 1.2.3 -> buildPhase: <last log line>
------------------------------------------------------------------------

Now Learn part of the output is where you educate users. You should only
show it when you know that a build will take some time and not annoy users of
the builds that take only few seconds.

Every feature like this should go through an intensive review and testing to
collect as much feedback as possible and to fine tune every little detail. If
done right this can be an awesome features beginners and advance users will
love, but if not done perfectly it will annoy users and leave bad impression.

Input

Input to a command is provided via ARGUMENTS and OPTIONS.

ARGUMENTS represent a required input for a function. When choosing to use
ARGUMENTS over OPTIONS please be aware of the downsides that come with it:

  • User will need to remember the order of ARGUMENTS. This is not a problem if
    there is only one ARGUMENT.
  • With OPTIONS it is possible to provide much better auto completion.
  • With OPTIONS it is possible to provide much better error message.
  • Using OPTIONS it will mean there is a little bit more typing.

We don’t discourage the use of ARGUMENTS, but simply want to make every
developer consider the downsides and choose wisely.

Naming the `OPTIONS`

The only naming convention - apart from the ones mentioned in Naming the
COMMANDS section is how flags are named.

Flags are a type of OPTION that represent an option that can be turned ON of
OFF. We can say flags are boolean type of **OPTION**.

Here are few examples of flag OPTIONS:

  • --colors vs. --no-colors (showing colors in the output)
  • --emojis vs. --no-emojis (showing emojis in the output)

Prompt when input not provided

For main commands (as per classification) we want command
to improve the discoverability of possible input. A new user will most likely
not know which ARGUMENTS and OPTIONS are required or which values are
possible for those options.

In case the user does not provide the input or they provide wrong input,
rather than show the error, prompt a user with an option to find and select
correct input (see examples).

Prompting is of course not required when TTY is not attached to STDIN. This
would mean that scripts won't need to handle prompt, but rather handle errors.

A place to use prompt and provide user with interactive select

shell
$ nix init
Initializing Nix project at `/path/to/here`.
      Select a template for you new project:
          |> py
             template#python-pip
             template#python-poetry
             [ Showing 2 templates from 1345 templates ]

Another great place to add prompts are confirmation dialogues for dangerous
actions
. For example when adding new substitutor via OPTIONS or via
flake.nix we should prompt - for the first time - and let user review what is
going to happen.

shell
$ nix build --option substitutors https://cache.example.org
------------------------------------------------------------------------
  Warning! A security related question needs to be answered.
------------------------------------------------------------------------
  The following substitutors will be used to in `my-project`:
    - https://cache.example.org

  Do you allow `my-project` to use above mentioned substitutors?
    [y/N] |> y

Output

Terminal output can be quite limiting in many ways. Which should force us to
think about the experience even more. As with every design the output is a
compromise between being terse and being verbose, between showing help to
beginners and annoying advance users. For this it is important that we know
what are the priorities.

Nix command line should be first and foremost written with beginners in mind.
But users won't stay beginners for long and what was once useful might quickly
become annoying. There is no golden rule that we can give in this guideline
that would make it easier how to draw a line and find best compromise.

What we would encourage is to build prototypes, do some user testing
and collect feedback. Then repeat the cycle few times.

First design the happy path and only after your iron it out, continue to work
on edge cases (handling and displaying errors, changes of the output by
certain OPTIONS, etc…)

Follow best practices

Needless to say we Nix must be a good citizen and follow best practices in
command line.

In short: STDOUT is for output, STDERR is for (human) messaging.

STDOUT and STDERR provide a way for you to output messages to the user while
also allowing them to redirect content to a file. For example:

shell
$ nix build > build.txt
------------------------------------------------------------------------
  Error! Attribute `bin` missing at (1:94) from string.
------------------------------------------------------------------------

  1| with import <nixpkgs> { }; (pkgs.runCommandCC or pkgs.runCommand) "shell" { buildInputs = [ (surge.bin) ]; } ""

Because this warning is on STDERR, it doesn’t end up in the file.

But not everything on STDERR is an error though. For example, you can run nix build and collect logs in a file while still seeing the progress.

text
$ nix build > build.txt
  Evaluated 1234 files in 1.2 seconds
 Downloaded python3.8-poetry 1.2.3 in 5.3 seconds
 Downloaded python3.8-requests 1.2.3 in 5.3 seconds
------------------------------------------------------------------------
      Press `v` to increase logs verbosity
         |> `?` to see other options
------------------------------------------------------------------------
      Learn something new with every build...
         |> See last logs of a build with `nix log --last` command.
------------------------------------------------------------------------
  Evaluated my-project 1.2.3 in 14.43 seconds
Downloading [12 / 200]
         |> firefox 1.2.3 [#########>       ] 10Mb/s | 2min left
   Building [2 / 20]
         |> glibc 1.2.3 -> buildPhase: <last log line>
------------------------------------------------------------------------

Errors (WIP)

TODO: Once we have implementation for the happy path then we will think
how to present errors.

Not only for humans

Terse, machine-readable output formats can also be useful but shouldn’t get in
the way of making beautiful CLI output. When needed, commands should offer a
--json flag to allow users to easily parse and script the CLI.

When TTY is not detected on STDOUT we should remove all design elements (no
colors, no emojis and using ASCII instead of Unicode symbols). The same should
happen when TTY is not detected on STDERR. We should not display progress /
status section, but only print warnings and errors.

Dialog with the user

CLIs don't always make it clear when an action has taken place. For every
action a user performs, your CLI should provide an equal and appropriate
reaction, clearly highlighting the what just happened. For example:

shell
$ nix build
 Downloaded python3.8-poetry 1.2.3 in 5.3 seconds
 Downloaded python3.8-requests 1.2.3 in 5.3 seconds
...
   Success! You have successfully built my-project.
$

Above command clearly states that command successfully completed. And in case
of nix build, which is a command that might take some time to complete, it is
equally important to also show that a command started.

Text alignment

Text alignment is the number one design element that will present all of the
Nix commands as a family and not as separate tools glued together.

The format we should follow is:

shell
$ nix COMMAND
   VERB_1 NOUN and other words
  VERB__1 NOUN and other words
       |> Some details

Few rules that we can extract from above example:

  • Each line should start at least with one space.
  • First word should be a VERB and must be aligned to the right.
  • Second word should be a NOUN and must be aligned to the left.
  • If you can not find a good VERB / NOUN pair, don’t worry make it as
    understandable to the user as possible.
  • More details of each line can be provided by |> character which is serving
    as the first word when aligning the text

Don’t forget you should also test your terminal output with colors and emojis
off (--no-colors --no-emojis).

Dim / Bright

After comparing few terminals with different color schemes we would recommend
to avoid using dimmed text
. The difference from the rest of the text is very
little in many terminal and color scheme combinations. Sometimes the difference
is not even notable, therefore relying on it wouldn’t make much sense.

The bright text is much better supported across terminals and color
schemes. Most of the time the difference is perceived as if the bright text
would be bold.

Colors

Humans are already conditioned by society to attach certain meaning to certain
colors. While the meaning is not universal, a simple collection of colors is
used to represent basic emotions.

Colors that can be used in output

  • Red = error, danger, stop
  • Green = success, good
  • Yellow/Orange = proceed with caution, warning, in progress
  • Blue/Magenta = stability, calm

While colors are nice, when command line is used by machines (in automation
scripts) you want to remove the colors. There should be a global --no-colors
option that would remove the colors.

Special (Unicode) characters

Most of the terminal have good support for Unicode characters and you should
use them in your output by default. But always have a backup solution that is
implemented only with ASCII characters and will be used when --ascii option
is going to be passed in. Please make sure that you test your output also
without Unicode characters

More they showing all the different Unicode characters it is important to
establish common set of characters that we use for certain situations.

Emojis

Emojis help channel emotions even better than text, colors and special
characters.

We recommend keeping the set of emojis to a minimum. This will enable each
emoji to stand out more.

As not everybody is happy about emojis we should provide an --no-emojis
option to disable them. Please make sure that you test your output also without
emojis.

Tables

All commands that are listing certain data can be implemented in some sort of a
table. It’s important that each row of your output is a single ‘entry’ of data.
Never output table borders. It’s noisy and a huge pain for parsing using other
tools such as grep.

Be mindful of the screen width. Only show a few columns by default with the
table header, for more the table can be manipulated by the following options:

  • --no-headers: Show column headers by default but allow to hide them.
  • --columns: Comma-separated list of column names to add.
  • --sort: Allow sorting by column. Allow inverse and multi-column sort as well.

Interactive output

Interactive output was selected to be able to strike the balance between
beginners and advance users. While the default output will target beginners it
can, with a few key strokes, be changed into and advance introspection tool.

Progress

For longer running commands we should provide and overview the progress.
This is shown best in nix build example:

shell
$ nix build
    Started building my-project 1.2.3
 Downloaded python3.8-poetry 1.2.3 in 5.3 seconds
 Downloaded python3.8-requests 1.2.3 in 5.3 seconds
------------------------------------------------------------------------
      Press `v` to increase logs verbosity
         |> `?` to see other options
------------------------------------------------------------------------
      Learn something new with every build...
         |> See last logs of a build with `nix log --last` command.
------------------------------------------------------------------------
  Evaluated my-project 1.2.3 in 14.43 seconds
Downloading [12 / 200]
         |> firefox 1.2.3 [#########>       ] 10Mb/s | 2min left
   Building [2 / 20]
         |> glibc 1.2.3 -> buildPhase: <last log line>
------------------------------------------------------------------------

Use a fzf like fuzzy search when there are multiple options to choose from.

shell
$ nix init
Initializing Nix project at `/path/to/here`.
      Select a template for you new project:
          |> py
             template#python-pip
             template#python-poetry
             [ Showing 2 templates from 1345 templates ]

Prompt

In some situations we need to prompt the user and inform the user about what is
going to happen.

shell
$ nix build --option substitutors https://cache.example.org
------------------------------------------------------------------------
  Warning! A security related question needs to be answered.
------------------------------------------------------------------------
  The following substitutors will be used to in `my-project`:
    - https://cache.example.org

  Do you allow `my-project` to use above mentioned substitutors?
    [y/N] |> y

Verbosity

There are many ways that you can control verbosity.

Verbosity levels are:

  • ERROR (level 0)
  • WARN (level 1)
  • NOTICE (level 2)
  • INFO (level 3)
  • TALKATIVE (level 4)
  • CHATTY (level 5)
  • DEBUG (level 6)
  • VOMIT (level 7)

The default level that the command starts is ERROR. The simplest way to
increase the verbosity by stacking -v option (eg: -vvv == level 3 == INFO).
There are also two shortcuts, --debug to run in DEBUG verbosity level and
--quiet to run in ERROR verbosity level.


Appendix 1: Commands naming exceptions

nix init and nix repl are well established


Doc Manual Source Development Contributing (`doc/manual/source/development/contributing.md`)

Contributing

Add a release note

doc/manual/rl-next contains release notes entries for all unreleased changes.

User-visible changes should come with a release note.

Add an entry

Here's what a complete entry looks like. The file name is not incorporated in the document.

text
---
synopsis: Basically a title
issues: 1234
prs: 1238
---

Here's one or more paragraphs that describe the change.

- It's markdown
- Add references to the manual using [links like this](@_at_docroot@/example.md)

Significant changes should add the following header, which moves them to the top.

text
significance: significant

See also the format documentation.

Build process

Releases have a precomputed rl-MAJOR.MINOR.md, and no rl-next.md.

Branches

Reverting

If a change turns out to be merged by mistake, or contain a regression, it may be reverted.
A revert is not a rejection of the contribution, but merely part of an effective development process.
It makes sure that development keeps running smoothly, with minimal uncertainty, and less overhead.
If maintainers have to worry too much about avoiding reverts, they would not be able to merge as much.
By embracing reverts as a good part of the development process, everyone wins.

However, taking a step back may be frustrating, so maintainers will be extra supportive on the next try.


Doc Manual Source Development Cxx (`doc/manual/source/development/cxx.md`)

C++ style guide

Some miscellaneous notes on how we write C++.
Formatting we hope to eventually normalize automatically, so this section is free to just discuss higher-level concerns.

The `*-impl.hh` pattern

Let's start with some background info first.
Headers, are supposed to contain declarations, not definitions.
This allows us to change a definition without changing the declaration, and have a very small rebuild during development.
Templates, however, need to be specialized to use-sites.
Absent fancier techniques, templates require that the definition, not just mere declaration, must be available at use-sites in order to make that specialization on the fly as part of compiling those use-sites.
Making definitions available like that means putting them in headers, but that is unfortunately means we get all the extra rebuilds we want to avoid by just putting declarations there as described above.

The *-impl.hh pattern is a ham-fisted partial solution to this problem.
It constitutes:

  • Declaring items only in the main foo.hh, including templates.

  • Putting template definitions in a companion foo-impl.hh header.

Most C++ developers would accompany this by having foo.hh include foo-impl.hh, to ensure any file getting the template declarations also got the template definitions.
But we've found not doing this has some benefits and fewer than imagined downsides.
The fact remains that headers are rarely as minimal as they could be;
there is often code that needs declarations from the headers but not the templates within them.
With our pattern where foo.hh doesn't include foo-impl.hh, that means they can just include foo.hh
Code that needs both just includes foo.hh and foo-impl.hh.
This does make linking error possible where something forgets to include foo-impl.hh that needs it, but those are build-time only as easy to fix.


Doc Manual Source Development Data Modeling (`doc/manual/source/development/data-modeling.md`)

Data Modeling Guidelines

Nix consumes and produces JSON and attribute sets in a variety of contexts.
These guidelines ensure consistent practices for our interfaces, for ease of use, and so that experience in one part carries over to another.

For these guidelines, we will use JSON terminology, but they apply equally well to new attribute set interfaces (primops, etc.).
Note that these are guidelines first and foremost. Exceptions include:

  • Feature testing: e.g., it is OK to do builtins?frobnicate.
  • Compatibility: we generally do not change stable interfaces just to make them comply. New replacements can be added with care.

Extensibility

The schema of JSON input and output should allow for backwards compatible extension.
This section explains how to achieve this.

Two definitions are helpful here, because while JSON only defines one "key-value" object type, we use it to cover two use cases:

  • dictionary: a map from names to value that all have the same type.
    In C++ this would be a std::map with string keys.

  • record: a fixed set of attributes each with their own type.
    In C++, this would be represented by a struct.

It is best not to mix these use cases, as that may lead to incompatibilities when the schema changes.
For example, adding a record field to a dictionary breaks consumers that assume all JSON object fields to have the same meaning and type, and dictionary items with a colliding name can not be represented anymore.

This leads to the following guidelines:

  • The top-level (root) value must be a record.

    Otherwise, one can not change the structure of a command's output.

  • The value of a dictionary item must be a record.

    Otherwise, the item type can not be extended.

  • List items should be records.

    Otherwise, one can not change the structure of the list items.

    If the order of the items does not matter, and each item has a unique key that is a string, consider representing the list as a dictionary instead.
    If the order of the items needs to be preserved, return a list of records.

  • Streaming JSON should return records.

    An example of a streaming JSON format is JSON lines, where each line represents a JSON value.
    These JSON values can be considered top-level values or list items, and they must be records.

Examples

This is bad, because all keys must be assumed to be store types:

json
{
  "local": { ... },
  "remote": { ... },
  "http": { ... }
}

This is good, because the it is extensible at the root, and is somewhat self-documenting:

json
{
  "storeTypes": { "local": { ... }, ... },
  "pluginSupport": true
}

While the dictionary of store types seems like a very complete response at first, a use case may arise that warrants returning additional information.
For example, the presence of plugin support may be crucial information for a client to proceed when their desired store type is missing.

The following representation is bad because it is not extensible:

json
{ "outputs": [ "out" "bin" ] }

However, simply converting everything to records is not enough, because the order of outputs must be preserved:

json
{ "outputs": { "bin": {}, "out": {} } }

The first item is the default output. Deriving this information from the outputs ordering is not great, but this is how Nix currently happens to work.
While it is possible for a JSON parser to preserve the order of fields, we can not rely on this capability to be present in all JSON libraries.

This representation is extensible and preserves the ordering:

json
{ "outputs": [ { "outputName": "out" }, { "outputName": "bin" } ] }

Self-describing values

As described in the previous section, it's crucial that schemas can be extended with new fields without breaking compatibility.
However, that should not mean we use the presence/absence of fields to indicate optional information within a version of the schema.
Instead, always include the field, and use null to indicate the "nothing" case.

Examples

Here are two JSON objects:

json
{
  "foo": {}
}
json
{
  "foo": {},
  "bar": {}
}

Since they differ in which fields they contain, they should not both be valid values of the same schema.
At most, they can match two different schemas where the second (with foo and bar) is considered a newer version of the first (with just foo).
Within each version, all fields are mandatory (always foo, and always foo and bar).
Only between each version, bar gets added as a new mandatory field.

Here are another two JSON objects:

json
{ "foo": null }
json
{ "foo": { "bar": 1 } }

Since they both contain a foo field, they could be valid values of the same schema.
The schema would have foo has an optional field, which is either null or an object where bar is an integer.


Doc Manual Source Development Debugging (`doc/manual/source/development/debugging.md`)

Debugging Nix

This section shows how to build and debug Nix with debug symbols enabled.

Additionally, see Testing Nix for further instructions on how to debug Nix in the context of a unit test or functional test.

Building Nix with Debug Symbols

In the development shell, mesonBuildType is set automatically to debugoptimized. This builds Nix with debug symbols, which are essential for effective debugging.

It is also possible to build without optimization for faster build:

console
[nix-shell]$ NIX_HARDENING_ENABLE=$(printLines $NIX_HARDENING_ENABLE | grep -v fortify)
[nix-shell]$ export mesonBuildType=debug

(The first line is needed because fortify hardening requires at least some optimization.)

Building Nix with sanitizers

Nix can be built with Address and
UB sanitizers using LLVM
or GCC. This is useful when debugging memory corruption issues.

console
[nix-shell]$ export mesonBuildType=debugoptimized
[nix-shell]$ appendToVar mesonFlags "-Dlibexpr:gc=disabled" # Disable Boehm
[nix-shell]$ appendToVar mesonFlags "-Db_sanitize=address,undefined"

Debugging the Nix Binary

Obtain your preferred debugger within the development shell:

console
[nix-shell]$ nix-shell -p gdb

On macOS, use lldb:

console
[nix-shell]$ nix-shell -p lldb

Launching the Debugger

To debug the Nix binary, run:

console
[nix-shell]$ gdb --args ../outputs/out/bin/nix

On macOS, use lldb:

console
[nix-shell]$ lldb -- ../outputs/out/bin/nix

Using the Debugger

Inside the debugger, you can set breakpoints, run the program, and inspect variables.

gdb
(gdb) break main
(gdb) run <arguments>

Refer to the GDB Documentation for comprehensive usage instructions.

On macOS, use lldb:

lldb
(lldb) breakpoint set --name main
(lldb) process launch -- <arguments>

Refer to the LLDB Tutorial for comprehensive usage instructions.


Doc Manual Source Development Documentation (`doc/manual/source/development/documentation.md`)

Contributing documentation

Improvements to documentation are very much appreciated, and a good way to start out with contributing to Nix.

This is how you can help:

Incremental refactorings of the documentation build setup to make it faster or easier to understand and maintain are also welcome.

Building the manual

Build the manual from scratch:

console
nix-build -E '(import ./.).packages.${builtins.currentSystem}.nix.doc'

or

console
nix build .#nix-manual

and open ./result/share/doc/nix/manual/index.html.

To build the manual incrementally, enter the development shell and configure with doc-gen enabled:

If using interactive nix develop:

console
$ nix develop
$ mesonFlags="$mesonFlags -Ddoc-gen=true" mesonConfigurePhase

If using direnv:

console
$ direnv allow
$ bash -c 'source $stdenv/setup && mesonFlags="$mesonFlags -Ddoc-gen=true" mesonConfigurePhase'

Then build the manual:

console
$ cd build
$ meson compile manual

The HTML manual will be generated at build/src/nix-manual/manual/index.html.

Style guide

The goal of this style guide is to make it such that

  • The manual is easy to search and skim for relevant information
  • Documentation sources are easy to edit
  • Changes to documentation are easy to review

You will notice that this is not implemented consistently yet.
Please follow the guide when making additions or changes to existing documentation.
Do not make sweeping changes, unless they are programmatic and can be validated easily.

Language

This manual is reference documentation.
The typical usage pattern is to look up isolated pieces of information.
It should therefore aim to be correct, consistent, complete, and easy to navigate at a glance.

  • Aim for clarity and brevity.

    Please take the time to read the plain language guidelines for details.

  • Describe the subject factually.

    In particular, do not make value judgements or recommendations.
    Check the code or add tests if in doubt.

  • Provide complete, minimal examples, and explain them.

    Readers should be able to try examples verbatim and get the same results as shown in the manual.
    Always describe in words what a given example does.

    Non-trivial examples may need additional explanation, especially if they use concepts from outside the given context.

  • Always explain code examples in the text.

    Use comments in code samples very sparingly, for instance to highlight a particular aspect.
    Readers tend to glance over large amounts of code when scanning for information.

    Especially beginners will likely find reading more complex-looking code strenuous and may therefore avoid it altogether.

    If a code sample appears to require a lot of inline explanation, consider replacing it with a simpler one.
    If that's not possible, break the example down into multiple parts, explain them separately, and then show the combined result at the end.
    This should be a last resort, as that would amount to writing a tutorial on the given subject.

  • Use British English.

    This is a somewhat arbitrary choice to force consistency, and accounts for the fact that a majority of Nix users and developers are from Europe.

Reference documentation must be readable in arbitrary order.
Readers cannot be expected to have any particular prerequisite knowledge about Nix.
While the table of contents can provide guidance and full-text search can help, they are most likely to find what they need by following sensible cross-references.

  • Link to technical terms

    When mentioning Nix-specific concepts, commands, options, settings, etc., link to appropriate documentation.
    Also link to external tools or concepts, especially if their meaning may be ambiguous.
    You may also want to link to definitions of less common technical terms.

    Then readers won't have to actively search for definitions and are more likely to discover relevant information on their own.

    Note

    man and --help pages don't display links.
    Use appropriate link texts such that readers of terminal output can infer search terms.

  • Do not break existing URLs between releases.

    There are countless links in the wild pointing to old versions of the manual.
    We want people to find up-to-date documentation when following popular advice.

    The current setup is cumbersome, and help making better automation is appreciated.

The build checks for broken internal links with.
This happens late in the process, so building the whole manual is not suitable for iterating quickly.
mdbook-linkcheck does not implement checking URI fragments yet.

Markdown conventions

The manual is written in markdown, and rendered with mdBook for the web and with lowdown for man pages and --help output.

For supported markdown features, refer to:

Please observe these guidelines to ease reviews:

  • Write one sentence per line.

    This makes long sentences immediately visible, and makes it easier to review changes and make direct suggestions.

  • Use reference links – sparingly – to ease source readability.
    Put definitions close to their first use.

    Example:

    text
    A [store object] contains a [file system object] and [references] to other store objects.
    
    [store object]: @docroot@/store/store-object.md
    [file system object]: @docroot@/architecture/file-system-object.md
    [references]: @docroot@/glossary.md#gloss-reference
  • Use admonitions of the following form:

    text
    > **Note**
    >
    > This is a note.

    Highlight examples as such:

    text
    > **Example**
    >
    > ```console
    > $ nix --version
    > ```

    Highlight syntax definitions as such, using EBNF notation:

    text
    > **Syntax**
    >
    > *attribute-set* = `{` [ *attribute-name* `=` *expression* `;` ... ] `}`

The `@docroot@` variable

@docroot@ provides a base path for links that occur in reusable snippets or other documentation that doesn't have a base path of its own.

If a broken link occurs in a snippet that was inserted into multiple generated files in different directories, use @docroot@ to reference the doc/manual/source directory.

If the @docroot@ literal appears in an error message from the mdbook-linkcheck tool, the @docroot@ replacement needs to be applied to the generated source file that mentions it.
See existing @docroot@ logic in the [Makefile for the manual].
Regular markdown files used for the manual have a base path of their own and they can use relative paths instead of @docroot@.

API documentation

Doxygen API documentation is available online.
You can also build and view it yourself:

console
$ nix build .#hydraJobs.internal-api-docs
$ xdg-open ./result/share/doc/nix/internal-api/html/index.html

or inside nix-shell or nix develop:

console
$ configurePhase
$ ninja src/internal-api-docs/html
$ xdg-open src/internal-api-docs/html/index.html

C API documentation

Note that the C API is not yet stable.
C API documentation is available online.
You can also build and view it yourself:

console
$ nix build .#hydraJobs.external-api-docs
$ xdg-open ./result/share/doc/nix/external-api/html/index.html

or inside nix-shell or nix develop:

text
$ configurePhase
$ ninja src/external-api-docs/html
$ xdg-open src/external-api-docs/html/index.html

If you use direnv, or otherwise want to run configurePhase in a transient shell, use:

bash
nix-shell -A devShells.x86_64-linux.native-clangStdenv --command 'appendToVar mesonFlags "-Ddoc-gen=true"; mesonConfigurePhase'

Doc Manual Source Development Experimental Features (`doc/manual/source/development/experimental-features.md`)

This section describes the notion of experimental features, and how it fits into the big picture of the development of Nix.

What are experimental features?

Experimental features are considered unstable, which means that they can be changed or removed at any time.
Users must explicitly enable them by toggling the associated experimental feature flags.
This allows accessing unstable functionality without unwittingly relying on it.

Experimental feature flags were first introduced in Nix 2.4.
Before that, Nix did have experimental features, but they were not guarded by flags and were merely documented as unstable.
This was a source of confusion and controversy.

When should a new feature be marked experimental?

A change in the Nix codebase should be guarded by an experimental feature flag if it is considered likely to be reverted or adapted in a backwards-incompatible manner after gathering more experience with it in practice.

Examples:

  • Changes to the Nix language, such as new built-ins, syntactic or semantic changes, etc.
  • Changes to the command-line interface

Lifecycle of an experimental feature

Experimental features have to be treated on a case-by-case basis.
However, the standard workflow for an experimental feature is as follows:

  • A new feature is implemented in a pull request
    • It is guarded by an experimental feature flag that is disabled by default
  • The pull request is merged, the experimental feature ends up in a release
    • Using the feature requires explicitly enabling it, signifying awareness of the potential risks
    • Being experimental, the feature can still be changed arbitrarily
  • The feature can be removed
    • The associated experimental feature flag is also removed
  • The feature can be declared stable
    • The associated experimental feature flag is removed
    • There should be enough evidence of users having tried the feature, such as feedback, fixed bugs, demonstrations of how it is put to use
    • Maintainers must feel confident that:
      • The feature is designed and implemented sensibly, that it is fit for purpose
      • Potential interactions are well-understood
      • Stabilising the feature will not incur an outsized maintenance burden in the future

The following diagram illustrates the process:

text
.------.
                  | idea |
                  '------'
                      |
       discussion, design, implementation
                      |
                      |     .-------.
                      |     |       |
                      v     v       |
               .--------------.  review
               | pull request |     |
               '--------------'     |
                   |     ^  |       |
                   |     |  '-------'
               .---'     '----.
               |              |
             merge       user feedback,
               |       (breaking) changes
               |              |
               '---.     .----'
                   |     |
                   v     |
               +--------------+
           .---| experimental |----.
           |   +--------------+    |
           |                       |
decision to stabilise      decision against
           |              keeping the feature
           |                       |
           v                       v
       +--------+             +---------+
       | stable |             | removed |
       +--------+             +---------+

Relation to the RFC process

Experimental features and RFCs both allow approaching substantial changes while minimizing the risk.
However they serve different purposes:

  • An experimental feature enables developers to iterate on and deliver a new idea without committing to it or requiring a costly long-running fork.
    It is primarily an issue of implementation, targeting Nix developers and early testers.
  • The goal of an RFC is to make explicit all the implications of a change:
    Explain why it is wanted, which new use-cases it enables, which interface changes it requires, etc.
    It is primarily an issue of design and communication, targeting the broader community.

This means that experimental features and RFCs are orthogonal mechanisms, and can be used independently or together as needed.

Currently available experimental features

{{#include ./experimental-feature-descriptions.md}}


Doc Manual Source Development Static Analysis (`doc/manual/source/development/static-analysis.md`)

Static Analysis

Nix uses clang-tidy for static analysis of C++ code.
This helps catch bugs, enforce coding standards, and maintain code quality.

Running clang-tidy locally

To run clang-tidy on the entire codebase in the development shell:

console
$ nix develop .#native-clangStdenv
$ configurePhase
$ meson compile -C build clang-tidy

This will analyze all C++ source files and report any warnings.

To automatically apply fixes for certain warnings:

console
$ meson compile -C build clang-tidy-fix

Warning

Review the changes before committing, as automatic fixes may not always be correct.

CI integration

clang-tidy runs automatically on every pull request via GitHub Actions.
The CI job builds .#hydraJobs.clangTidy.x86_64-linux which:

  1. Builds all components with debug mode (for faster compilation)
  2. Runs clang-tidy on each component
  3. Fails if any warnings are found (warnings are treated as errors)

Configuration

The clang-tidy configuration is in .clang-tidy at the repository root (symlinked from nix-meson-build-support/common/clang-tidy/.clang-tidy).

Suppressing warnings

If a warning is a false positive, you can suppress it in several ways:

  1. Inline suppression (preferred for specific cases):

    cpp
    // NOLINTBEGIN(bugprone-some-check)
    ... code ...
    // NOLINTEND(bugprone-some-check)

    Or for a single line:

    cpp
    int x = something(); // NOLINT(bugprone-some-check)
  2. Configuration file (for project-wide suppression):
    Add the check to the disabled list in .clang-tidy:

    yaml
    Checks:
      - -bugprone-some-check  # Reason for disabling
  3. Check options (for configuring check behavior):

    yaml
    CheckOptions:
      bugprone-reserved-identifier.AllowedIdentifiers: '__some_identifier'

Adding new checks

To enable additional checks:

  1. Edit nix-meson-build-support/common/clang-tidy/.clang-tidy
  2. Add the check to the Checks list
  3. Run clang-tidy locally to see the impact
  4. Fix any new warnings or disable specific sub-checks if needed

Custom clang-tidy plugin

The Nix project includes infrastructure for custom clang-tidy checks in src/clang-tidy-plugin/.
These checks can enforce Nix-specific coding patterns that aren't covered by standard clang-tidy checks.

To add a new custom check:

  1. Add the check implementation in src/clang-tidy-plugin/
  2. Register it in nix-clang-tidy-checks.cc
  3. Enable it in .clang-tidy with the nix- prefix

Doc Manual Source Development Testing (`doc/manual/source/development/testing.md`)

Running tests

Coverage analysis

A coverage analysis report is available online
You can build it yourself:

text
# nix build .#hydraJobs.coverage
# xdg-open ./result/index.html

Extensive records of build metrics, such as test coverage over time, are also available online.

Unit-tests

The unit tests are defined using the googletest and rapidcheck frameworks.

Source and header layout

An example of some files, demonstrating much of what is described below

text
src
├── libexpr
│   ├── meson.build
│   ├── include/nix/expr/value/context.hh
│   ├── value/context.cc
│   …
│
├── libutil-tests
│   ├── meson.build
│   …
│   ├── data
│   │   ├── git/tree.txt
│       …
│
├── libexpr-test-support
│   ├── meson.build
│   ├── include/nix/expr
│   │   ├── meson.build
│   │   └── tests
│   │       ├── value/context.hh
│   │       …
│   ├── tests
│       ├── value/context.cc
│       …
│
├── libexpr-tests
│   ├── meson.build
│   ├── value/context.cc
│    …
…

The tests for each Nix library (libnixexpr, libnixstore, etc..) live inside a directory src/${library_name_without-nix}-test.
Given an interface (header) and implementation pair in the original library, say, src/libexpr/include/nix/expr/value/context.hh and src/libexpr/value/context.cc, we write tests for it in src/libexpr-tests/value/context.cc, and (possibly) declare/define additional interfaces for testing purposes in src/libexpr-test-support/include/nix/expr/tests/value/context.hh and src/libexpr-test-support/tests/value/context.cc.

Data for unit tests is stored in a data subdir of the directory for each unit test executable.
For example, libnixstore code is in src/libstore, and its test data is in src/libstore-tests/data.
The path to the src/${library_name_without-nix}-test/data directory is passed to the unit test executable with the environment variable _NIX_TEST_UNIT_DATA.
Note that each executable only gets the data for its tests.

The unit test libraries are in src/${library_name_without-nix}-test-support.
All headers are in a tests subdirectory so they are included with #include "nix/tests/".

The use of all these separate directories for the unit tests might seem inconvenient, as for example the tests are not "right next to" the part of the code they are testing.
But organizing the tests this way has one big benefit:
there is no risk of any build-system wildcards for the library accidentally picking up test code that should not built and installed as part of the library.

Running tests

You can run the whole testsuite with meson test from the Meson build directory, or the tests for a specific component with meson test nix-store-tests.
The environment variables that Google Test accepts are also worth knowing:

  1. GTEST_FILTER

    This is used for finer-grained filtering of which tests to run.

  2. GTEST_BRIEF

    This is used to avoid logging passing tests.

  3. GTEST_BREAK_ON_FAILURE

    This is used to create a debugger breakpoint when an assertion failure occurs.

Putting the first two together, one might run

bash
GTEST_BRIEF=1 GTEST_FILTER='ErrorTraceTest.*' meson test nix-expr-tests -v

for short but comprensive output.

Debugging tests

For debugging, it is useful to combine the third option above with Meson's --gdb flag:

bash
GTEST_BRIEF=1 GTEST_FILTER='Group.my-failing-test' meson test nix-expr-tests --gdb

This will:

  1. Run the unit test with GDB

  2. Run just Group.my-failing-test

  3. Stop the program when the test fails, allowing the user to then issue arbitrary commands to GDB.

Characterisation testing { #characterisation-testing-unit }

See functional characterisation testing for a broader discussion of characterisation testing.

Like with the functional characterisation, _NIX_TEST_ACCEPT=1 is also used.
For example:

shell-session
$ _NIX_TEST_ACCEPT=1 meson test nix-store-tests -v
...
[  SKIPPED ] WorkerProtoTest.string_read
[  SKIPPED ] WorkerProtoTest.string_write
[  SKIPPED ] WorkerProtoTest.storePath_read
[  SKIPPED ] WorkerProtoTest.storePath_write
...

will regenerate the "golden master" expected result for the libnixstore characterisation tests.
The characterisation tests will mark themselves "skipped" since they regenerated the expected result instead of actually testing anything.

JSON Schema testing

In doc/manual/source/protocols/json/ we have a number of manual pages generated from JSON Schema.
That JSON schema is tested against the JSON file test data used in characterisation tests for JSON (de)serialization, in src/json-schema-checks.
Between the JSON (de)serialization testing, and this testing of the same data against the schema, we make sure that the manual, the implementation, and a machine-readable schema are are all in sync.

Unit test support libraries

There are headers and code which are not just used to test the library in question, but also downstream libraries.
For example, we do property testing with the rapidcheck library.
This requires writing Arbitrary "instances", which are used to describe how to generate values of a given type for the sake of running property tests.
Because types contain other types, Arbitrary "instances" for some type are not just useful for testing that type, but also any other type that contains it.
Downstream types frequently contain upstream types, so it is very important that we share arbitrary instances so that downstream libraries' property tests can also use them.

It is important that these testing libraries don't contain any actual tests themselves.
On some platforms they would be run as part of every test executable that uses them, which is redundant.
On other platforms they wouldn't be run at all.

Functional tests

The functional tests reside under the tests/functional directory and are listed in tests/functional/meson.build.
Each test is a bash script.

Functional tests are run during installCheck in the nix package build, as well as separately from the build, in VM tests.

Running the whole test suite

The whole test suite (functional and unit tests) can be run with:

shell-session
$ checkPhase

Grouping tests

Sometimes it is useful to group related tests so they can be easily run together without running the entire test suite.
Each test group is in a subdirectory of tests.
For example, tests/functional/ca/meson.build defines a ca test group for content-addressing derivation outputs.

That test group can be run like this:

shell-session
$ meson test --suite ca
ninja: Entering directory `/home/jcericson/src/nix/master/build'
ninja: no work to do.
[1-20/20] 🌑 nix-functional-tests:ca / ca/why-depends                                1/20 nix-functional-tests:ca / ca/nix-run                                  OK               0.16s
[2-20/20] 🌒 nix-functional-tests:ca / ca/why-depends                                2/20 nix-functional-tests:ca / ca/import-derivation                        OK               0.17s

Running individual tests

Individual tests can be run with meson:

shell-session
$ meson test --verbose ${testName}
ninja: Entering directory `/home/jcericson/src/nix/master/build'
ninja: no work to do.
1/1 nix-functional-tests:main / ${testName}        OK               0.41s

Ok:                 1
Expected Fail:      0
Fail:               0
Unexpected Pass:    0
Skipped:            0
Timeout:            0

Full log written to /home/jcericson/src/nix/master/build/meson-logs/testlog.txt

The --verbose flag will make Meson also show the console output of each test for easier debugging.
The test script will then be traced with set -x and the output displayed as it happens,
regardless of whether the test succeeds or fails.

Tests can be also run directly without meson:

shell-session
$ TEST_NAME=${testName} NIX_REMOTE='' PS4='+(${BASH_SOURCE[0]-$0}:$LINENO) tests/functional/${testName}.sh
+(${testName}.sh:1) foo
output from foo
+(${testName}.sh:2) bar
output from bar
...

Debugging failing functional tests

When a functional test fails, it usually does so somewhere in the middle of the script.

To figure out what's wrong, it is convenient to run the test regularly up to the failing nix command, and then run that command with a debugger like GDB.

For example, if the script looks like:

bash
foo
nix blah blub
bar

edit it like so:

diff
foo
-nix blah blub
+gdb --args nix blah blub
 bar

Then, running the test with --interactive will prevent Meson from hijacking the terminal so you can drop you into GDB once the script reaches that point:

shell-session
$ meson test ${testName} --interactive
...
+ gdb blash blub
GNU gdb (GDB) 12.1
...
(gdb)

One can debug the Nix invocation in all the usual ways.
For example, enter run to start the Nix invocation.

Characterisation testing { #characterisation-testing-functional }

Occasionally, Nix utilizes a technique called Characterisation Testing as part of the functional tests.
This technique is to include the exact output/behavior of a former version of Nix in a test in order to check that Nix continues to produce the same behavior going forward.

For example, this technique is used for the language tests, to check both the printed final value if evaluation was successful, and any errors and warnings encountered.

It is frequently useful to regenerate the expected output.
To do that, rerun the failed test(s) with _NIX_TEST_ACCEPT=1.
For example:

bash
_NIX_TEST_ACCEPT=1 meson test lang

This convention is shared with the characterisation unit tests too.

An interesting situation to document is the case when these tests are "overfitted".
The language tests are, again, an example of this.
The expected successful output of evaluation is supposed to be highly stable – we do not intend to make breaking changes to (the stable parts of) the Nix language.
However, the errors and warnings during evaluation (successful or not) are not stable in this way.
We are free to change how they are displayed at any time.

It may be surprising that we would test non-normative behavior like diagnostic outputs.
Diagnostic outputs are indeed not a stable interface, but they still are important to users.
By recording the expected output, the test suite guards against accidental changes, and ensure the result (not just the code that implements it) of the diagnostic code paths are under code review.
Regressions are caught, and improvements always show up in code review.

To ensure that characterisation testing doesn't make it harder to intentionally change these interfaces, there always must be an easy way to regenerate the expected output, as we do with _NIX_TEST_ACCEPT=1.

Running functional tests on NixOS

We run the functional tests not just in the build, but also in VM tests.
This helps us ensure that Nix works correctly on NixOS, and environments that have similar characteristics that are hard to reproduce in a build environment.

These can be run with:

shell
nix build .#hydraJobs.tests.functional_user

Generally, this build is sufficient, but in nightly or CI we also test the attributes functional_root and functional_trusted, in which the test suite is run with different levels of authorization.

Integration tests

The integration tests are defined in the Nix flake under the hydraJobs.tests attribute.
These tests include everything that needs to interact with external services or run Nix in a non-trivial distributed setup.
Because these tests are expensive and require more than what the standard github-actions setup provides, most of them only run on the master branch (on https://hydra.nixos.org/jobset/nix/master).

You can run them manually with nix build .#hydraJobs.tests.{testName} or nix-build -A hydraJobs.tests.{testName}.

Fuzzing

The project uses libFuzzer and LLVM coverage instrumentation to fuzz sensitive pieces of code.
The harnesses reside in corresponding -tests subprojects (e.g. src/libutil-tests/fuzz).
The fuzzers option builds the harnesses independently of unit-tests; set unit-tests=false for a fuzzer-only build.
The fuzzing-engine option accepts one compiler-driver argument for linking an external fuzzing engine.
If fuzzing-engine is empty, Meson requires Clang and fuzzer-no-link in b_sanitize.
The compiler driver then links the harnesses with libFuzzer and libstdc++.

shell
nix develop .#native-clangStdenv
appendToVar mesonFlags "-Dunit-tests=false"
appendToVar mesonFlags "-Dfuzzers=true"
appendToVar mesonFlags "-Db_sanitize=address,undefined,fuzzer-no-link"
# Clang sanitizer/shared-library workaround: https://github.com/mesonbuild/meson/issues/764
appendToVar mesonFlags "-Db_lundef=false"
appendToVar mesonFlags "-Dlibexpr:gc=disabled" # Because Boehm doesn't play well with ASan
configurePhase
buildPhase

To use an external fuzzing engine, set fuzzing-engine:

shell
mesonFlagsArray+=(
  "-Dunit-tests=false"
  "-Dfuzzers=true"
  "-Dfuzzing-engine=$LIB_FUZZING_ENGINE"
)

Nix passes this value as one compiler-driver argument.
The caller must also choose a compatible compiler and C++ runtime and provide any required instrumentation and sanitizer flags.

If you want to collect coverage metrics you also need to specify the following compiler flags before running the configurePhase:

shell
export CXXFLAGS="-fprofile-instr-generate -fcoverage-mapping"
export CCFLAGS="-fprofile-instr-generate -fcoverage-mapping"

For now, the testbenches are mostly rudimentary and are supposed to catch memory safety bugs, but fuzzing is also crucial for validating invariants.
Contributions improving harnesses and corpus/dictionaries are welcome.

To run the harness (e.g. for NAR deserialisation) you can execute the following:

shell
export LLVM_PROFILE_FILE="default.%p.profraw"
mkdir /tmp/parse-dump
build/src/libutil-tests/fuzz/harnesses/fuzz-parse-dump -runs=1000000 -max_len=65536 -dict=./src/libutil-tests/fuzz/data/nars.dict /tmp/parse-dump ./src/libutil-tests/fuzz/data/nars

Note that to achieve better results, tuning libFuzzer parameters or improvements to the initial corpus and dictionaries is likely required. For further information consult the libFuzzer manual.

If you want to inspect the coverage, wait for the harness to run to completion (interrupting it won't produce a non-empty .profraw file) and assemble the final coverage report:

text
llvm-profdata merge -sparse *.profraw -o default.profdata
llvm-cov show build/src/libutil/libnixutil.so -instr-profile=default.profdata -format=html -output-dir cov-html
xdg-open cov-html/index.html

If you have found a memory safety issue using fuzzing, consider reporting it privately if you deem the issue to be security relevant.

Checks that defeat fuzzing

Fuzzing is crucial for validating invariants, but a few invariants are ones a fuzzer can never satisfy.
A check that a field equals a cryptographic hash of other fields is the usual case: passing it requires a hash preimage, so the code below the check becomes unreachable to the fuzzer rather than merely hard to reach.
This is different from a check that is only awkward to satisfy --- sorted keys, balanced delimiters, no redundant escapes --- which a coverage-guided fuzzer will learn to get past on its own.
Only the former should be gated.

Such checks are compiled out under FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION, e.g.:

c++
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
    if (path != computedPath)
        throw FormatError(...);
#endif

The macro name is a convention from OSS-Fuzz and libFuzzer.
nix-meson-build-support/common/meson.build defines it for every subproject when fuzzer-no-link is in b_sanitize, which is exactly when a fuzzer-instrumented build is being made.
Builds using an external fuzzing-engine are expected to pass it themselves, as OSS-Fuzz does.

Anything gated this way is no longer exercised by the fuzzer, so it must be covered by a unit test instead.
For an example of both halves, see the fixed-output derivation path check in parseOutput (src/libstore/derivation/aterm.cc) and its test CAFixedPathMismatch.

Installer tests

GitHub Actions CI in the Nix repository also tests the installer on PRs. It does not require additional setup and utilises GHA Artifacts and can be run in any Nix repository fork.

  • The tests job generates installers for the platforms below and uploads them as an artifact:

    • x86_64-linux
    • aarch64-darwin
  • The installer_test job (which runs on Linux and macOS) will try to install Nix with the cached installer and run a trivial Nix command.

  • Both the scripted installer and the standalone Rust-based installer are tested.

You can generate the installer tarball and script manually by running nix build .#hydraJobs.installerScriptForGHA.<system-double>.

Working on documentation

Using the CI-generated installer for manual testing

After the CI run completes, you can check the output to extract the installer artifact:

  1. Click into the detailed view of the CI run.

  2. Scroll down to Artifacts section.

  3. Download the corresponding installer artifact (installer-darwin for aarch64-darwin and installer-linux for x86_64-linux).

  4. Unpack the downloaded .zip artifact.

  5. To generate an install command, plug the path to the unpacked artifact into this template:

    console
    sh <path/to/artifact>/install --tarball-url-prefix file://<path/to/artifact>

Doc Manual Source Installation Building Source (`doc/manual/source/installation/building-source.md`)

Building Nix from Source

Nix is built with Meson.
It is broken up into multiple Meson packages, which are optionally combined in a single project using Meson's subprojects feature.

There are no mandatory extra steps to the building process:
generic Meson installation instructions like this should work.

bash
git clone https://github.com/NixOS/nix.git
cd nix
meson setup build
cd build
ninja
(sudo) ninja install

The installation path can be specified by passing -Dprefix=prefix
to meson setup build. The default installation directory is /usr/local. You
can change this to any location you like. You must have write permission
to the prefix path.

Nix keeps its store (the place where packages are stored) in
/nix/store by default. This can be changed using
-Dlibstore:store-dir=path.

Warning

It is best not to change the Nix store from its default, since doing
so makes it impossible to use pre-built binaries from the standard
Nixpkgs channels — that is, all packages will need to be built from
source.

Nix keeps state (such as its database and log files) in /nix/var by
default. This can be changed using -Dlocalstatedir=path.


Doc Manual Source Installation Env Variables (`doc/manual/source/installation/env-variables.md`)

Environment Variables

To use Nix, some environment variables should be set. In particular,
PATH should contain the directories prefix/bin and
~/.nix-profile/bin. The first directory contains the Nix tools
themselves, while ~/.nix-profile is a symbolic link to the current
user environment (an automatically generated package consisting of
symlinks to installed packages). The simplest way to set the required
environment variables is to include the file
prefix/etc/profile.d/nix.sh in your ~/.profile (or similar), like
this:

bash
source prefix/etc/profile.d/nix.sh

`NIX_SSL_CERT_FILE`

If you need to specify a custom certificate bundle to account for an
HTTPS-intercepting man in the middle proxy, you must specify the path to
the certificate bundle in the environment variable NIX_SSL_CERT_FILE.

If you don't specify a NIX_SSL_CERT_FILE manually, Nix will install
and use its own certificate bundle.

Set the environment variable and install Nix

console
$ export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt
$ curl -L https://nixos.org/nix/install | sh

In the shell profile and rc files (for example, /etc/bashrc,
/etc/zshrc), add the following line:

bash
export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt

Note

You must not add the export and then do the install, as the Nix
installer will detect the presence of Nix configuration, and abort.

If you use the Nix daemon, you should also add the following to
/etc/nix/nix.conf:

text
ssl-cert-file = /etc/ssl/my-certificate-bundle.crt

Proxy Environment Variables

The Nix installer has special handling for these proxy-related
environment variables: http_proxy, https_proxy, ftp_proxy,
all_proxy, no_proxy, HTTP_PROXY, HTTPS_PROXY, FTP_PROXY,
ALL_PROXY, NO_PROXY.

If any of these variables are set when running the Nix installer, then
the installer will create an override file at
/etc/systemd/system/nix-daemon.service.d/override.conf so nix-daemon
will use them.


Doc Manual Source Installation Installing Binary (`doc/manual/source/installation/installing-binary.md`)

Installing a Binary Distribution

Updating to macOS 15 Sequoia

If you recently updated to macOS 15 Sequoia and are getting

console
error: the user '_nixbld1' in the group 'nixbld' does not exist

when running Nix commands, refer to GitHub issue NixOS/nix#10892 for instructions to fix your installation without reinstalling.

To install the latest version Nix, run the following command:

console
$ curl -L https://nixos.org/nix/install | sh

This performs the default type of installation for your platform:

  • Multi-user:
    • Linux with systemd and without SELinux
    • macOS
  • Single-user:
    • Linux without systemd
    • Linux with SELinux

We recommend the multi-user installation if it supports your platform and you can authenticate with sudo.

The installer can be configured with various command line arguments and environment variables.
To show available command line flags:

console
$ curl -L https://nixos.org/nix/install | sh -s -- --help

To check what it does and how it can be customised further, download and edit the second-stage installation script.

Installing a pinned Nix version from a URL

Version-specific installation URLs for all Nix versions since 1.11.16 can be found at releases.nixos.org.
The directory for each version contains the corresponding SHA-256 hash.

All installation scripts are invoked the same way:

console
$ export VERSION=2.19.2 
$ curl -L https://releases.nixos.org/nix/nix-$VERSION/install | sh

Multi User Installation

The multi-user Nix installation creates system users and a system service for the Nix daemon.

Supported systems:

  • Linux running systemd, with SELinux disabled
  • macOS

To explicitly instruct the installer to perform a multi-user installation on your system:

console
$ bash <(curl -L https://nixos.org/nix/install) --daemon

You can run this under your usual user account or root.
The script will invoke sudo as needed.

Single User Installation

To explicitly select a single-user installation on your system:

console
$ bash <(curl -L https://nixos.org/nix/install) --no-daemon

In a single-user installation, /nix is owned by the invoking user.
The script will invoke sudo to create /nix if it doesn’t already exist.
If you don’t have sudo, manually create /nix as root:

console
$ su root
# mkdir /nix
# chown alice /nix

Installing from a binary tarball

You can also download a binary tarball that contains Nix and all its dependencies:

Example

console
$ pushd $(mktemp -d)
$ export VERSION=2.19.2
$ export SYSTEM=x86_64-linux
$ curl -LO https://releases.nixos.org/nix/nix-$VERSION/nix-$VERSION-$SYSTEM.tar.xz
$ tar xfj nix-$VERSION-$SYSTEM.tar.xz
$ cd nix-$VERSION-$SYSTEM
$ ./install
$ popd

The installer can be customised with the environment variables declared in the file named install-multi-user.

Native packages for Linux distributions

The Nix community maintains installers for some Linux distributions in their native packaging format(https://nix-community.github.io/nix-installers/).

macOS Installation

[]{#sect-macos-installation-change-store-prefix}[]{#sect-macos-installation-encrypted-volume}[]{#sect-macos-installation-symlink}[]{#sect-macos-installation-recommended-notes}

We believe we have ironed out how to cleanly support the read-only root file system
on modern macOS. New installs will do this automatically.

This section previously detailed the situation, options, and trade-offs,
but it now only outlines what the installer does. You don't need to know
this to run the installer, but it may help if you run into trouble:

  • create a new APFS volume for your Nix store

  • update /etc/synthetic.conf to direct macOS to create a "synthetic"
    empty root directory to mount your volume

  • specify mount options for the volume in /etc/fstab

    • rw: read-write
    • noauto: prevent the system from auto-mounting the volume (so the
      LaunchDaemon mentioned below can control mounting it, and to avoid
      masking problems with that mounting service).
    • nobrowse: prevent the Nix Store volume from showing up on your
      desktop; also keeps Spotlight from spending resources to index
      this volume
  • if you have FileVault enabled

    • generate an encryption password
    • put it in your system Keychain
    • use it to encrypt the volume
  • create a system LaunchDaemon to mount this volume early enough in the
    boot process to avoid problems loading or restoring any programs that
    need access to your Nix store


Doc Manual Source Installation Installing Docker (`doc/manual/source/installation/installing-docker.md`)

Using Nix within Docker

To run the latest stable release of Nix with Docker run the following command:

console
$ docker run -ti docker.io/nixos/nix
Unable to find image 'docker.io/nixos/nix:latest' locally
latest: Pulling from docker.io/nixos/nix
5843afab3874: Pull complete
b52bf13f109c: Pull complete
1e2415612aa3: Pull complete
Digest: sha256:27f6e7f60227e959ee7ece361f75d4844a40e1cc6878b6868fe30140420031ff
Status: Downloaded newer image for docker.io/nixos/nix:latest
35ca4ada6e96:/# nix --version
nix (Nix) 2.3.12
35ca4ada6e96:/# exit

If you want the latest pre-release you can use ghcr.io/nixos/nix and view them at https://github.com/nixos/nix/pkgs/container/nix

What is included in Nix's Docker image?

The official Docker image is created using pkgs.dockerTools.buildLayeredImage
(and not with Dockerfile as it is usual with Docker images). You can still
base your custom Docker image on it as you would do with any other Docker
image.

The Docker image is not based on any other image and includes a minimal set
of runtime dependencies that are required to use Nix.

Docker image with the latest development version of Nix

To get the latest image that was built by Hydra run
the following command:

console
$ curl -L https://hydra.nixos.org/job/nix/master/dockerImage.x86_64-linux/latest/download/1 | docker load
$ docker run -ti nix:2.5pre20211105

You can also build a Docker image from source yourself:

console
$ nix build ./\#hydraJobs.dockerImage.x86_64-linux
$ docker load -i ./result/image.tar.gz
$ docker run -ti nix:2.5pre20211105

Docker image with non-root Nix

If you would like to run Nix in a container under a user other than root,
you can build an image with a non-root single-user installation of Nix
by specifying the uid, gid, uname, and gname arguments to docker.nix:

console
$ nix build --file docker.nix \
    --arg uid 1000 \
    --arg gid 1000 \
    --argstr uname user \
    --argstr gname user \
    --argstr name nix-user \
    --out-link nix-user.tar.gz
$ docker load -i nix-user.tar.gz
$ docker run -ti nix-user

Doc Manual Source Installation Installing Source (`doc/manual/source/installation/installing-source.md`)

Installing Nix from Source

If no binary package is available or if you want to hack on Nix, you
can build Nix from its Git repository.


Doc Manual Source Installation Multi User (`doc/manual/source/installation/multi-user.md`)

Multi-User Mode

To allow a Nix store to be shared safely among multiple users, it is
important that users are not able to run builders that modify the Nix
store or database in arbitrary ways, or that interfere with builds
started by other users. If they could do so, they could install a Trojan
horse in some package and compromise the accounts of other users.

To prevent this, the Nix store and database are owned by some privileged
user (usually root) and builders are executed under special user
accounts (usually named nixbld1, nixbld2, etc.). When a unprivileged
user runs a Nix command, actions that operate on the Nix store (such as
builds) are forwarded to a Nix daemon running under the owner of the
Nix store/database that performs the operation.

Note

Multi-user mode has one important limitation: only root and a set of
trusted users specified in nix.conf can specify arbitrary binary
caches. So while unprivileged users may install packages from
arbitrary Nix expressions, they may not get pre-built binaries.

Setting up the build users

The build users are the special UIDs under which builds are performed.
They should all be members of the build users group nixbld. This
group should have no other members. The build users should not be
members of any other group. On Linux, you can create the group and users
as follows:

console
$ groupadd -r nixbld
$ for n in $(seq 1 10); do useradd -c "Nix build user $n" \
    -d /var/empty -g nixbld -G nixbld -M -N -r -s "$(which nologin)" \
    nixbld$n; done

This creates 10 build users. There can never be more concurrent builds
than the number of build users, so you may want to increase this if you
expect to do many builds at the same time.

Running the daemon

The Nix daemon should be started as
follows (as root):

console
$ nix-daemon

You’ll want to put that line somewhere in your system’s boot scripts.

To let unprivileged users use the daemon, they should set the
NIX_REMOTE environment variable to
daemon. So you should put a line like

console
export NIX_REMOTE=daemon

into the users’ login scripts.

Restricting access

To limit which users can perform Nix operations, you can use the
permissions on the directory /nix/var/nix/daemon-socket. For instance,
if you want to restrict the use of Nix to the members of a group called
nix-users, do

console
$ chgrp nix-users /nix/var/nix/daemon-socket
$ chmod ug=rwx,o= /nix/var/nix/daemon-socket

This way, users who are not in the nix-users group cannot connect to
the Unix domain socket /nix/var/nix/daemon-socket/socket, so they
cannot perform Nix operations.


Doc Manual Source Installation Nix Security (`doc/manual/source/installation/nix-security.md`)

Security

Nix has two basic security models. First, it can be used in “single-user
mode”, which is similar to what most other package management tools do:
there is a single user (typically root) who performs all package
management operations. All other users can then use the installed
packages, but they cannot perform package management operations
themselves.

Alternatively, you can configure Nix in “multi-user mode”. In this
model, all users can perform package management operations — for
instance, every user can install software without requiring root
privileges. Nix ensures that this is secure. For instance, it’s not
possible for one user to overwrite a package used by another user with a
Trojan horse.


Doc Manual Source Installation Obtaining Source (`doc/manual/source/installation/obtaining-source.md`)

Obtaining the Source

The most recent sources of Nix can be obtained from its Git
repository
. For example, the following
command will check out the latest revision into a directory called
nix:

console
$ git clone https://github.com/NixOS/nix

Likewise, specific releases can be obtained from the
tags of the repository.


Doc Manual Source Installation Prerequisites Source (`doc/manual/source/installation/prerequisites-source.md`)

Prerequisites

This list and lower version bounds are maintained on best-effort basis. When in doubt, check the meson.build files.

  • Meson build system (https://github.com/mesonbuild/meson).

  • Ninja (https://ninja-build.org/).

  • A version of GCC or Clang that supports C++23 (anything newer than Clang 19 or GCC 14 is likely to work).

  • pkg-config to locate dependencies.
    If your distribution does not provide it, you can get it from http://www.freedesktop.org/wiki/Software/pkg-config.

  • The OpenSSL library to calculate cryptographic hashes.
    If your distribution does not provide it, you can get it from https://www.openssl.org.

  • The libbrotlienc and libbrotlidec libraries to provide implementation of the Brotli compression algorithm.
    They are available for download from the official repository https://github.com/google/brotli.

  • cURL library.
    If your distribution does not provide it, you can get it from https://curl.haxx.se/.

  • The SQLite embedded database library, version 3.6.19 or higher.
    If your distribution does not provide it, please install it from http://www.sqlite.org/.

  • The Boehm garbage collector (bdw-gc) to reduce the evaluator’s memory consumption (optional).
    To enable it, install pkgconfig and the Boehm garbage collector, and pass the option -Dlibexpr:gc=enabled to meson setup.

  • The boost library of version 1.87.0 or higher.
    It can be obtained from the official web site https://www.boost.org/.

  • The editline library of version 1.14.0 or higher.
    It can be obtained from the its repository https://github.com/troglobit/editline.

  • The libsodium library for verifying cryptographic signatures of contents fetched from binary caches.
    It can be obtained from the official web site https://libsodium.org.

  • Recent versions of Bison and Flex to build the parser.
    (This is because Nix needs C++ template support in Bison and reentrancy support in Flex.)

  • The libseccomp is used to provide syscall filtering on Linux.
    This is an optional dependency and can be disabled passing a -Dlibstore:seccomp-sandboxing=disabled option to the meson setup command
    (Not recommended unless your system doesn't support libseccomp).
    To get the library, visit https://github.com/seccomp/libseccomp.

  • On 64-bit x86 machines only, libcpuid library is used to determine which microarchitecture levels are supported
    (e.g., as whether to have x86_64-v2-linux among additional system types).
    The library is available from its homepage http://libcpuid.sourceforge.net.
    This is an optional dependency and can be disabled by providing a -Dlibutil:cpuid=disabled option to meson setup script.

  • Unless meson setup build -Dunit-tests=false is specified, GoogleTest (GTest) and RapidCheck are required, which are available at
    https://google.github.io/googletest/ and https://github.com/emil-e/rapidcheck respectively.


Doc Manual Source Installation Single User (`doc/manual/source/installation/single-user.md`)

Single-User Mode

In single-user mode, all Nix operations that access the database in
prefix/var/nix/db or modify the Nix store in prefix/store must be
performed under the user ID that owns those directories. This is
typically root. (If you install from RPM packages, that’s in fact the
default ownership.) However, on single-user machines, it is often
convenient to chown those directories to your normal user account so
that you don’t have to su to root all the time.


Doc Manual Source Installation Supported Platforms (`doc/manual/source/installation/supported-platforms.md`)

Supported Platforms

Nix is currently supported on the following platforms:

  • Linux (i686, x86_64, aarch64).

  • macOS (x86_64, aarch64).


Doc Manual Source Installation Uninstall (`doc/manual/source/installation/uninstall.md`)

Uninstalling Nix

Multi User

Removing a multi-user installation depends on the operating system.

Linux

If you are on Linux with systemd:

  1. Remove the Nix daemon service:

    console
    sudo systemctl stop nix-daemon.service
    sudo systemctl disable nix-daemon.socket nix-daemon.service
    sudo systemctl daemon-reload
  2. Remove files created by Nix:

    console
    sudo rm -rf /etc/nix /etc/profile.d/nix.sh /etc/tmpfiles.d/nix-daemon.conf /nix ~/.local/share/nix ~/.local/state/nix ~/.cache/nix ~/.nix-defexpr ~/.nix-profile ~/.nix-channels ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile ~root/.cache/nix
  3. Remove build users and their group:

    console
    for i in $(seq 1 32); do
      sudo userdel nixbld$i
    done
    sudo groupdel nixbld
  4. There may also be references to Nix in

    • /etc/bash.bashrc
    • /etc/bashrc
    • /etc/profile
    • /etc/zsh/zshrc
    • /etc/zshrc

    which you may remove.

FreeBSD

  1. Stop and remove the Nix daemon service:

    console
    sudo service nix-daemon stop
    sudo rm -f /usr/local/etc/rc.d/nix-daemon
    sudo sysrc -x nix_daemon_enable
  2. Remove files created by Nix:

    console
    sudo rm -rf /etc/nix /usr/local/etc/profile.d/nix.sh /nix ~/.local/share/nix ~/.local/state/nix ~/.cache/nix ~/.nix-defexpr ~/.nix-profile ~/.nix-channels ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile ~root/.cache/nix
  3. Remove build users and their group:

    console
    for i in $(seq 1 32); do
      sudo pw userdel nixbld$i
    done
    sudo pw groupdel nixbld
  4. There may also be references to Nix in:

    • /usr/local/etc/bashrc
    • /usr/local/etc/zshrc
    • Shell configuration files in users' home directories

    which you may remove.

macOS

Updating to macOS 15 Sequoia

If you recently updated to macOS 15 Sequoia and are getting

console
error: the user '_nixbld1' in the group 'nixbld' does not exist

when running Nix commands, refer to GitHub issue NixOS/nix#10892 for instructions to fix your installation without reinstalling.

  1. If system-wide shell initialisation files haven't been altered since installing Nix, use the backups made by the installer:

    console
    sudo mv /etc/zshrc.backup-before-nix /etc/zshrc
    sudo mv /etc/bashrc.backup-before-nix /etc/bashrc
    sudo mv /etc/bash.bashrc.backup-before-nix /etc/bash.bashrc

    Otherwise, edit /etc/zshrc, /etc/bashrc, and /etc/bash.bashrc to remove the lines sourcing nix-daemon.sh, which should look like this:

    bash
    # Nix
    if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
      . '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
    fi
    # End Nix
  2. Stop and remove the Nix daemon services:

    console
    sudo launchctl unload /Library/LaunchDaemons/org.nixos.nix-daemon.plist
    sudo rm /Library/LaunchDaemons/org.nixos.nix-daemon.plist
    sudo launchctl unload /Library/LaunchDaemons/org.nixos.darwin-store.plist
    sudo rm /Library/LaunchDaemons/org.nixos.darwin-store.plist

    This stops the Nix daemon and prevents it from being started next time you boot the system.

  3. Remove the nixbld group and the _nixbuildN users:

    console
    sudo dscl . -delete /Groups/nixbld
    for u in $(sudo dscl . -list /Users | grep _nixbld); do sudo dscl . -delete /Users/$u; done

    This will remove all the build users that no longer serve a purpose.

  4. Edit fstab using sudo vifs to remove the line mounting the Nix Store volume on /nix, which looks like

    text
    UUID=<uuid> /nix apfs rw,noauto,nobrowse,suid,owners

    or

    text
    LABEL=Nix\040Store /nix apfs rw,nobrowse

    by setting the cursor on the respective line using the arrow keys, and pressing dd, and then :wq to save the file.

    This will prevent automatic mounting of the Nix Store volume.

  5. Edit /etc/synthetic.conf to remove the nix line.
    If this is the only line in the file you can remove it entirely:

    bash
    if [ -f /etc/synthetic.conf ]; then
      if [ "$(cat /etc/synthetic.conf)" = "nix" ]; then
        sudo rm /etc/synthetic.conf
      else
        sudo vi /etc/synthetic.conf
      fi
    fi

    This will prevent the creation of the empty /nix directory.

  6. Remove the files Nix added to your system, except for the store:

    console
    sudo rm -rf /etc/nix /var/root/.nix-profile /var/root/.nix-defexpr /var/root/.nix-channels ~/.nix-profile ~/.nix-defexpr ~/.nix-channels ~/.local/share/nix ~/.local/state/nix ~/.cache/nix
  7. Remove the Nix Store volume:

    console
    sudo diskutil apfs deleteVolume /nix

    This will remove the Nix Store volume and everything that was added to the store.

    If the output indicates that the command couldn't remove the volume, you should make sure you don't have an unmounted Nix Store volume.
    Look for a "Nix Store" volume in the output of the following command:

    console
    diskutil list

    If you do find a "Nix Store" volume, delete it by running diskutil apfs deleteVolume with the store volume's diskXsY identifier.

    If you get an error that the volume is in use by the kernel, reboot and immediately delete the volume before starting any other process.

Note

After you complete the steps here, you will still have an empty /nix directory.
This is an expected sign of a successful uninstall.
The empty /nix directory will disappear the next time you reboot.

You do not have to reboot to finish uninstalling Nix.
The uninstall is complete.
macOS (Catalina+) directly controls root directories, and its read-only root will prevent you from manually deleting the empty /nix mountpoint.

Single User

To remove a single-user installation of Nix, run:

console
rm -rf /nix ~/.nix-channels ~/.nix-defexpr ~/.nix-profile ~/.local/share/nix ~/.local/state/nix ~/.cache/nix

You might also want to manually remove references to Nix from your ~/.profile.


Doc Manual Source Installation Upgrading (`doc/manual/source/installation/upgrading.md`)

Upgrading Nix

Note

These upgrade instructions apply where Nix was installed following the installation instructions in this manual.

Check which Nix version will be installed, for example from one of the release channels such as nixpkgs-unstable:

console
$ nix-shell -p nix -I nixpkgs=channel:nixpkgs-unstable --run "nix --version"
nix (Nix) 2.18.1

Warning

Writing to the local store with a newer version of Nix, for example by building derivations with nix-build or nix-store --realise, may change the database schema!
Reverting to an older version of Nix may therefore require purging the store database before it can be used.

Linux multi-user

console
$ sudo su
# nix-env --install --file '<nixpkgs>' --attr nix cacert -I nixpkgs=channel:nixpkgs-unstable
# systemctl daemon-reload
# systemctl restart nix-daemon

macOS multi-user

console
$ sudo nix-env --install --file '<nixpkgs>' --attr nix cacert -I nixpkgs=channel:nixpkgs-unstable
$ sudo launchctl remove org.nixos.nix-daemon
$ sudo launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist

Single-user all platforms

console
$ nix-env --install --file '<nixpkgs>' --attr nix cacert -I nixpkgs=channel:nixpkgs-unstable

Doc Manual Source Language Advanced Attributes (`doc/manual/source/language/advanced-attributes.md`)

Advanced Attributes

Derivations can declare some infrequently used optional attributes.

Inputs

  • [exportReferencesGraph]{#adv-attr-exportReferencesGraph}
    Specifies the export references graph option.
    The value of this attribute should be a list of pairs [ name1 path1 name2 path2 ... ].
    For example, when the following derivation is built:

    nix
    derivation {
      ...
      exportReferencesGraph = [ "libfoo-graph" libfoo ];
    };

    the references graph of libfoo is placed in the file
    libfoo-graph in the temporary build directory.

  • [passAsFile]{#adv-attr-passAsFile}
    A list of names of attributes whose environment variables should be marked
    pass as file.
    For example, if you have

    nix
    passAsFile = ["big"];
    big = "a very long string";

    then when the builder runs, the environment variable bigPath
    will contain the absolute path to a temporary file containing a very long string.

  • [__structuredAttrs]{#adv-attr-structuredAttrs}
    If the special attribute __structuredAttrs is set to true, the other derivation
    attributes are serialised into a file in JSON format.

    See the corresponding section in the derivation page for further details.

    Warning

    If set to true, the top-level attributes allowedReferences, allowedRequisites,
    disallowedReferences and disallowedRequisites
    will have no effect; use outputChecks instead.

Output checks

These attributes specify checks on the derivation's outputs.
The concepts behind them are documented there; this section gives the syntax for specifying them from the Nix language.

Store paths in these lists may be given as strings with context (i.e. by interpolating a derivation), and outputs of the derivation itself are denoted by their plain output names, e.g. "out".

  • [allowedReferences]{#adv-attr-allowedReferences}
    Specifies the allowed references check. For example,

    nix
    allowedReferences = [];

    enforces that the output of a derivation cannot have any runtime
    dependencies on its inputs. To allow an output to have a runtime
    dependency on itself, use "out" as a list item.

  • [allowedRequisites]{#adv-attr-allowedRequisites}
    Specifies the allowed requisites check. For example,

    nix
    allowedRequisites = [ foobar ];

    enforces that the output of a derivation cannot have any other
    runtime dependency than foobar, and in addition it enforces that
    foobar itself doesn't introduce any other dependency itself.

  • [disallowedReferences]{#adv-attr-disallowedReferences}
    Specifies the disallowed references check. For example,

    nix
    disallowedReferences = [ foo ];

    enforces that the output of a derivation cannot have a direct
    runtime dependency on the derivation foo.

  • [disallowedRequisites]{#adv-attr-disallowedRequisites}
    Specifies the disallowed requisites check. For example,

    nix
    disallowedRequisites = [ foobar ];

    enforces that the output of a derivation cannot have any runtime
    dependency on foobar or any other derivation depending recursively
    on foobar.

  • [outputChecks]{#adv-attr-outputChecks}
    When using structured attributes, the outputChecks
    attribute allows defining checks per-output.

    In addition to
    allowedReferences, allowedRequisites,
    disallowedReferences and disallowedRequisites,
    the following attributes are available:

    Example:

    nix
    __structuredAttrs = true;
    
    outputChecks.out = {
      # The closure of 'out' must not be larger than 256 MiB.
      maxClosureSize = 256 * 1024 * 1024;
    
      # It must not refer to the C compiler or to the 'dev' output.
      disallowedRequisites = [ stdenv.cc "dev" ];
    };
    
    outputChecks.dev = {
      # The 'dev' output must not be larger than 128 KiB.
      maxSize = 128 * 1024;
    };

Other output modifications

  • [unsafeDiscardReferences]{#adv-attr-unsafeDiscardReferences}
    When using structured attributes, the
    attribute unsafeDiscardReferences is an attribute set with a boolean value for each output name.
    If set to true, it enables the
    unsafe discard references
    behavior for that output.

    Example:

    nix
    __structuredAttrs = true;
    unsafeDiscardReferences.out = true;

Build scheduling

  • [preferLocalBuild]{#adv-attr-preferLocalBuild}
    If set to true, enables the prefer local build option.
    This is useful for derivations that are cheapest to build locally.

  • [allowSubstitutes]{#adv-attr-allowSubstitutes}
    If set to false, disables the allow substitutes option, so Nix will always build this derivation (locally or remotely) rather than substituting its outputs.
    This is useful for derivations that are cheaper to build than to substitute.

  • [requiredSystemFeatures]{#adv-attr-requiredSystemFeatures}
    Specifies the required system features option:
    Nix will only build the derivation on a machine that has the corresponding features set in its system-features configuration.

    For example, setting

    nix
    requiredSystemFeatures = [ "kvm" ];

    ensures that the derivation can only be built on a machine with the kvm feature.

Impure builder configuration

  • [impureEnvVars]{#adv-attr-impureEnvVars}
    Specifies the impure environment variables option: a list of environment variables
    that should be passed from the environment of the calling user to the builder. For example,
    fetchurl in Nixpkgs has the line

    nix
    impureEnvVars = [ "http_proxy" "https_proxy" ... ];

    to make it use the proxy server configuration specified by the user
    in the environment variables http_proxy and friends.

Setting the derivation type

As discussed in Derivation Outputs and Types of Derivations, there are multiples kinds of derivations / kinds of derivation outputs.
The choice of the following attributes determines which kind of derivation we are making.

The three types of derivations are chosen based on the following combinations of these attributes.
All other combinations are invalid.

Here is more information on the output* attributes, and what values they may be set to:

  • outputHashMode{#adv-attr-outputHashMode}

    This specifies how the files of a content-addressing derivation output are digested to produce a content address.

    This works in conjunction with outputHashAlgo.
    Specifying one without the other is an error (unless [outputHash is also specified and includes its own hash algorithm as described below).

    The outputHashMode attribute determines how the hash is computed.
    It must be one of the following values:

    • "flat"

      This is the default.

    • "recursive" or "nar"

      Compatibility

      "recursive" is the traditional way of indicating this,
      and is supported since 2005 (virtually the entire history of Nix).
      "nar" is more clear, and consistent with other parts of Nix (such as the CLI),
      however support for it is only added in Nix version 2.21.

    • "text"

      Warning

      The use of this method for derivation outputs is part of the dynamic-derivations experimental feature.

    • "git"

      Warning

      This method is part of the git-hashing experimental feature.

    See content-addressing store objects for more information about the process this flag controls.

  • outputHashAlgo{#adv-attr-outputHashAlgo}

    This specifies the hash algorithm used to digest the file system object data of a content-addressing derivation output.

    This works in conjunction with outputHashMode.
    Specifying one without the other is an error (unless outputHash is also specified and includes its own hash algorithm as described below).

    The outputHashAlgo attribute specifies the hash algorithm used to compute the hash.
    It can currently be "blake3", "sha1", "sha256", "sha512", or null.

    outputHashAlgo can only be null when outputHash follows the SRI format, because in that case the choice of hash algorithm is determined by outputHash.

  • outputHash{#adv-attr-outputHash}

    This will specify the output hash of the single output of a fixed-output derivation.

    The outputHash attribute must be a string containing the hash in either hexadecimal or "nix32" encoding, or following the format for integrity metadata as defined by SRI.
    The "nix32" encoding is Nix's variant of Base32 encoding.

    Note

    The convertHash function shows how to convert between different encodings.
    The nix-hash command has information about obtaining the hash for some contents, as well as converting to and from encodings.

  • __contentAddressed{#adv-attr-__contentAddressed}

    Warning

    This attribute is part of an experimental feature.

    To use this attribute, you must enable the
    ca-derivations experimental feature.
    For example, in nix.conf you could add:

    text
    extra-experimental-features = ca-derivations

    This is a boolean with a default of false.
    It determines whether the derivation is floating content-addressing.


Doc Manual Source Language Builtins Prefix (`doc/manual/source/language/builtins-prefix.md`)

Built-ins

This section lists the values and functions built into the Nix language evaluator.
All built-ins are available through the global builtins constant.

Some built-ins are also exposed directly in the global scope:

Tip

Should I use builtins or lib?

The built-ins are designed to be a stable interface that expressions can depend on over time,
so that, for instance, old Nixpkgs versions continue to evaluate reproducibly.

On the flip side, this means they have accumulated a few quirks that Nix is unable to change,
but a library like Nixpkgs lib can improve, replace or deprecate those behaviors,
because its sources are pinned where reproducibility matters.

So while it is not wrong to use builtins directly,
for instance in small Nixpkgs-independent projects,
you will have a better experience using a library like lib as your primary source of functions,
as it hides problematic functions, fixes up others,
and helps you improve your code by means of future deprecations, which are still sufficiently rare.

[`derivation attrs`](#builtins-derivation)
derivation is described in [its own section](derivations.md).

Doc Manual Source Language Derivations (`doc/manual/source/language/derivations.md`)

Derivations

The most important built-in function is derivation, which is used to describe a single store-layer store derivation.
Consult the store chapter for what a store derivation is;
this section just concerns how to create one from the Nix language.

This builtin function takes as input an attribute set, the attributes of which specify the inputs to the process.
It outputs an attribute set, and produces a store derivation as a side effect of evaluation.

Input attributes

Required

  • [name]{#attr-name} (String)

    A symbolic name for the derivation.
    See derivation outputs for what this is affects.

    Example

    nix
    derivation {
      name = "hello";
      # ...
    }

    The derivation's path will be /nix/store/<hash>-hello.drv.
    The output paths will be of the form /nix/store/<hash>-hello[-<output>]

  • [system]{#attr-system} (String)

    See system.

    Example

    Declare a derivation to be built on a specific system type:

    nix
    derivation {
      # ...
      system = "x86_64-linux";
      # ...
    }

    Example

    Declare a derivation to be built on the system type that evaluates the expression:

    nix
    derivation {
      # ...
      system = builtins.currentSystem;
      # ...
    }

    builtins.currentSystem has the value of the system configuration option, and defaults to the system type of the current Nix installation.

  • [builder]{#attr-builder} (Path | String)

    See builder.

    Example

    Use the file located at /bin/bash as the builder executable:

    nix
    derivation {
      # ...
      builder = "/bin/bash";
      # ...
    };

    Example

    Copy a local file to the Nix store for use as the builder executable:

    nix
    derivation {
      # ...
      builder = ./builder.sh;
      # ...
    };

    Example

    Use a file from another derivation as the builder executable:

    nix
    let pkgs = import <nixpkgs> {}; in
    derivation {
      # ...
      builder = "${pkgs.python}/bin/python";
      # ...
    };

Optional

  • [args]{#attr-args} (List of String)

    Default: [ ]

    See args.

    Example

    Pass arguments to Bash to interpret a shell command:

    nix
    derivation {
      # ...
      builder = "/bin/bash";
      args = [ "-c" "echo hello world > $out" ];
      # ...
    };
  • [outputs]{#attr-outputs} (List of String)

    Default: [ "out" ]

    Symbolic outputs of the derivation.
    Each output name is passed to the builder executable as an environment variable with its value set to the corresponding store path.

    By default, a derivation produces a single output called out.
    However, derivations can produce multiple outputs.
    This allows the associated store objects and their closures to be copied or garbage-collected separately.

    Example

    Imagine a library package that provides a dynamic library, header files, and documentation.
    A program that links against such a library doesn’t need the header files and documentation at runtime, and it doesn’t need the documentation at build time.
    Thus, the library package could specify:

    nix
    derivation {
      # ...
      outputs = [ "lib" "dev" "doc" ];
      # ...
    }

    This will cause Nix to pass environment variables lib, dev, and doc to the builder containing the intended store paths of each output.
    The builder would typically do something like

    bash
    ./configure \
      --libdir=$lib/lib \
      --includedir=$dev/include \
      --docdir=$doc/share/doc

    for an Autoconf-style package.

    The name of an output is combined with the name of the derivation to create the name part of the output's store path, unless it is out, in which case just the name of the derivation is used.

    Example

    nix
    derivation {
      name = "example";
      outputs = [ "lib" "dev" "doc" "out" ];
      # ...
    }

    The store derivation path will be /nix/store/<hash>-example.drv.
    The output paths will be

    • /nix/store/<hash>-example-lib
    • /nix/store/<hash>-example-dev
    • /nix/store/<hash>-example-doc
    • /nix/store/<hash>-example

    You can refer to each output of a derivation by selecting it as an attribute.
    The first element of outputs determines the default output and ends up at the top-level.

    Example

    Select an output by attribute name:

    nix
    let
      myPackage = derivation {
        name = "example";
        outputs = [ "lib" "dev" "doc" "out" ];
        # ...
      };
    in myPackage.dev

    Since lib is the first output, myPackage is equivalent to myPackage.lib.

  • See Advanced Attributes for more, infrequently used, optional attributes.

  • Every other attribute is passed as an environment variable to the builder.
    Attribute values are translated to environment variables as follows:

    • Strings are passed unchanged.

    • Integral numbers are converted to decimal notation.

    • Floating point numbers are converted to simple decimal or scientific notation with a preset precision.

    • A path (e.g., ../foo/sources.tar) causes the referenced file
      to be copied to the store; its location in the store is put in
      the environment variable. The idea is that all sources should
      reside in the Nix store, since all inputs to a derivation should
      reside in the Nix store.

    • A derivation causes that derivation to be built prior to the
      present derivation. The environment variable is set to the store path of the derivation's default output.

    • Lists of the previous types are also allowed. They are simply
      concatenated, separated by spaces.

    • true is passed as the string 1, false and null are
      passed as an empty string.


Doc Manual Source Language Evaluation (`doc/manual/source/language/evaluation.md`)

Evaluation

Evaluation is the process of turning a Nix expression into a Nix value.

This happens by a number of rules, such as:

  • Constructing values from literals.
    For example the number literal 1 is turned into the number value 1.
  • Applying operators
    For example the addition operator + is applied to two number values to produce a new number value.
  • Applying built-in functions
    For example the expression builtins.isInt 1 is evaluated to true.
  • Applying user-defined functions
    For example the expression (x: x + 1) 10 can* be thought of rewriting x in the function body to the argument, 10 + 1, which is then evaluated to 11.

These rules are applied as needed, driven by the specific use of the expression. For example, this can occur in the Nix command line interface or interactively with the repl (read-eval-print loop), which is a useful tool when learning about evaluation.

Details

Values {#values}

Nix values can be thought of as a subset of Nix expressions.
For example, the expression 1 + 2 is not a value, because it can be reduced to 3. The expression 3 is a value, because it cannot be reduced any further.

Evaluation normally happens by applying rules to the "head" of the expression, which is the outermost part of the expression. The head of an expression like [ 1 2 ] is the list literal ([ a1 a2 ]), for 1 + 2 it is the addition operator (+), and for f 1 it is the function application "operator" ( ).

After applying all possible rules to the head until no rules can be applied, the expression is in "weak head normal form" (WHNF). This means that the outermost constructor of the expression is evaluated, but the inner values may or may not be. "Weak" only signifies that the expression may be a function. This is an historical or academic artifact, and Nix has no use for the non-weak "head normal form".

Laziness and thunks {#laziness}

The Nix language implements call by need (as opposed to call by value or call by reference). Call by need is commonly known as laziness in functional programming, as it is a specific implementation of the concept where evaluation is deferred until the result is required, aiming to only evaluate the parts of an expression that are needed to produce the final result.

Furthermore, the result of evaluation is preserved, in values, in let bindings, in function parameters, which behave a lot like let bindings, but with the notable exception of function calls. Results of function calls rely on being put into let bindings, etc to be reused.

When discussing the process of evaluation in lower level terms, we may define values not as a subset of expressions, but separately, where each "value" is either a data constructor, a function or a thunk. A thunk is a delayed computation, represented by an expression reference and a "closure" – the values for the lexical scope around the delayed expression.

As a user of the language, you generally don't have to think about thunks, as they are not part of the language semantics, but you may encounter them in the repl, in the C API or in discussions.

Strictness

Instead of thinking about thunks, it is often more productive to think in terms of strictness.
This term is used in functional programming to refer to the opposite of laziness, i.e. not just for something like error propagation. It refers to the need to evaluate certain expressions before evaluation can produce any result.

Statements about strictness usually implicitly refer to weak head normal form.
For example, we can say that the following function is strict in its argument:

nix
x: isAttrs x || isFunction x

The above function must be strict in its argument x because determining its type requires evaluating x to at least some degree.

The following function is not strict in its argument:

nix
x: { isOk = isAttrs x || isFunction x; }

It is not strict, because it can return the attribute set before evaluating x.
The attribute value for isOk is strict in x.

A function with a set pattern is always strict in its argument, as a consequence of checking the argument's type and/or attribute names:

nix
let f = { ... }: "ok";
in f (throw "kablam")
=> error: kablam

However, a set pattern does not add any strictness beyond WHNF of the attribute set argument.

nix
let f = orig@{ x, ... }: "ok";
in f { x = throw "error"; y = throw "error"; }
=> "ok"

Evaluation order

The order in which expressions are evaluated is generally unspecified, because it does not affect successful evaluation outcomes.
This allows more freedom for the evaluator to evolve and to evaluate efficiently.

Data dependencies naturally impose some ordering constraints: a value cannot be used before it is computed.
Beyond these constraints, the evaluator is free to choose any order.

The order in which side effects such as builtins.trace output occurs is not defined, but may be expected to follow data dependencies.

In a lazy language, evaluation order is often opposite to expectations from strict languages.
For example, in let wrap = x: { wrapped = x; }; in wrap (1 + 2), the function body produces a result ({ wrapped = ...; }) before evaluating x.

Infinite recursion and stack overflow

During evaluation, two types of errors can occur when expressions reference themselves or call functions too deeply:

Infinite recursion

This error occurs when a value depends on itself through a cycle, making it impossible to compute.

nix
let x = x; in x
=> error: infinite recursion encountered

Infinite recursion happens at the value level when evaluating an expression requires evaluating the same expression again.

Despite the name, infinite recursion is cheap to compute and does not involve a stack overflow.
The cycle is finite and fairly easy to detect.

Stack overflow

This error occurs when the call depth exceeds the maximum allowed limit.

nix
let f = x: f (x + 1);
in f 0
=> error: stack overflow; max-call-depth exceeded

Stack overflow happens when too many function calls are nested without returning.
The maximum call depth is controlled by the max-call-depth setting.


Doc Manual Source Language Identifiers (`doc/manual/source/language/identifiers.md`)

Identifiers

An identifier is an ASCII character sequence that:

  • Starts with a letter (a-z, A-Z) or underscore (_)
  • Can contain any number of:
    • Letters (a-z, A-Z)
    • Digits (0-9)
    • Underscores (_)
    • Apostrophes (')
    • Hyphens (-)
  • Is not one of the keywords

Syntax

identifier ~ [A-Za-z_][A-Za-z0-9_'-]*

Names

A name can be written as an identifier or a string literal.

Syntax

name → identifier | string

Names are used in attribute sets, let bindings, and inherit.
Two names are the same if they represent the same sequence of characters, regardless of whether they are written as identifiers or strings.

Keywords

These keywords are reserved and cannot be used as identifiers:

Note

The Nix language evaluator currently allows or to be used as a name in some contexts, for backwards compatibility reasons.
Users are advised not to rely on this.

There are long-standing issues with how or is parsed as a name, which can't be resolved without making a breaking change to the language.


Doc Manual Source Language Import From Derivation (`doc/manual/source/language/import-from-derivation.md`)

Import From Derivation

The value of a Nix expression can depend on the contents of a store object.

Passing an expression expr that evaluates to a store path to any built-in function which reads from the filesystem constitutes Import From Derivation (IFD):

When the store path needs to be accessed, evaluation will be paused, the corresponding store object realised, and then evaluation resumed.

This has performance implications:
Evaluation can only finish when all required store objects are realised.
Since the Nix language evaluator is sequential, it only finds store paths to read from one at a time.
While realisation is always parallel, in this case it cannot be done for all required store paths at once, and is therefore much slower than otherwise.

Realising store objects during evaluation can be disabled by setting allow-import-from-derivation to false.
Without IFD it is ensured that evaluation is complete and Nix can produce a build plan before starting any realisation.

Example

In the following Nix expression, the inner derivation drv produces a file with contents hello.

nix
# IFD.nix
let
  drv = derivation {
    name = "hello";
    builder = "/bin/sh";
    args = [ "-c" "echo -n hello > $out" ];
    system = builtins.currentSystem;
  };
in "${builtins.readFile drv} world"
shellsession
nix-instantiate IFD.nix --eval --read-write-mode
text
building '/nix/store/348q1cal6sdgfxs8zqi9v8llrsn4kqkq-hello.drv'...
"hello world"

The contents of the derivation's output have to be realised before they can be read with readFile.
Only then evaluation can continue to produce the final result.

Illustration

As a first approximation, the following data flow graph shows how evaluation and building are interleaved, if the value of a Nix expression depends on realising a store object.
Boxes are data structures, arrow labels are transformations.

text
/* Detailed source-code truncated for AI context efficiency. */

In more detail, the following sequence diagram shows how the expression is evaluated step by step, and where evaluation is blocked to wait for the build output to appear.

text
/* Detailed source-code truncated for AI context efficiency. */

Doc Manual Source Language Operators (`doc/manual/source/language/operators.md`)

Operators

Name Syntax Associativity Precedence
Attribute selection attrset . attrpath [ or expr ] none 1
Function application func expr left 2
Arithmetic negation - number none 3
Has attribute expr ? attrpath none 4
List concatenation list ++ list right 5
Multiplication number * number left 6
Division number / number left 6
Subtraction number - number left 7
Addition number + number left 7
String concatenation string + string left 7
Path concatenation path + path left 7
Path and string concatenation path + string left 7
String and path concatenation string + path left 7
Logical negation (NOT) ! bool none 8
Update attrset // attrset right 9
Less than expr < expr none 10
Less than or equal to expr <= expr none 10
Greater than expr > expr none 10
Greater than or equal to expr >= expr none 10
Equality expr == expr none 11
Inequality expr != expr none 11
Logical conjunction (AND) bool && bool left 12
Logical disjunction (OR) bool || bool left 13
Logical implication bool -> bool right 14
Pipe operator (experimental) expr |> func left 15
Pipe operator (experimental) func <| expr right 15

Attribute selection

Syntax

attrset . attrpath [ or expr ]

Select the attribute denoted by attribute path attrpath from attribute set attrset.
If the attribute doesn’t exist, return the expr after or if provided, otherwise abort evaluation.

Function application

Syntax

func expr

Apply the callable value func to the argument expr. Note the absence of any visible operator symbol.
A callable value is either:

Warning

List items are also separated by whitespace, which means that function calls in list items must be enclosed by parentheses.

Has attribute

Syntax

expr ? attrpath

Test whether expr is an attribute set containing the attribute denoted by attrpath.
If attrpath contains multiple components, and any of its components (other than the last) do not correspond to an attribute set in expr, the result is false.
The result is a Boolean value.

See also: builtins.hasAttr

After evaluating attrset and attrpath, the computational complexity is O(log(n)) for n attributes in the attrset.

Arithmetic

Numbers will retain their type unless mixed with other numeric types:
Pure integer operations will always return integers, whereas any operation involving at least one floating point number returns a floating point number.

Evaluation of the following numeric operations throws an evaluation error:

  • Division by zero
  • Integer overflow, that is, any operation yielding a result outside of the representable range of Nix language integers

See also Comparison and Equality.

The + operator is overloaded to also work on strings and paths.

String concatenation

Syntax

string + string

Concatenate two strings and merge their string contexts.

Path concatenation

Syntax

path + path

Concatenate two paths.
The result is a path.

Path and string concatenation

Syntax

path + string

Concatenate path with string.
The result is a path.

Note

The string must not have a string context that refers to a store path.

String and path concatenation

Syntax

string + path

Concatenate string with path.
The result is a string.

Important

The file or directory at path must exist and is copied to the store.
The path appears in the result as the corresponding store path.

Update

Syntax

attrset1 // attrset2

Update attribute set attrset1 with names and values from attrset2.

The returned attribute set will have all of the attributes in attrset1 and attrset2.
If an attribute name is present in both, the attribute value from the latter is taken.

This operator is strict in both attrset1 and attrset2.
That means that both arguments are evaluated to weak head normal form, so the attribute sets themselves are evaluated, but their attribute values are not evaluated.

Comparison

Comparison is

  • arithmetic for numbers
  • lexicographic for strings and paths
  • item-wise lexicographic for lists:
    elements at the same index in both lists are compared according to their type and skipped if they are equal.

All comparison operators are implemented in terms of <, and the following equivalencies hold:

comparison implementation
a <= b ! ( b < a )
a > b b < a
a >= b ! ( a < b )

Equality

  • Attribute sets are compared first by attribute names and then by items until a difference is found.
  • Lists are compared first by length and then by items until a difference is found.
  • Comparison of distinct functions returns false, but identical functions may be subject to value identity optimization.
  • Numbers are type-compatible, see arithmetic operators.
  • Floating point numbers only differ up to a limited precision.

The == operator is strict in both arguments; when comparing composite types (attribute sets and lists), it is partially strict in their contained values: they are evaluated until a difference is found.

Value identity optimization

Nix performs equality comparisons of nested values by pointer equality or more abstractly, identity.
Nix semantics ideally do not assign a unique identity to values as they are created, but equality is an exception to this rule.
The disputable benefit of this is that it is more efficient, and it allows cyclical structures to be compared, e.g. let x = { x = x; }; in x == x evaluates to true.
However, as a consequence, it makes a function equal to itself when the comparison is made in a list or attribute set, in contradiction to a simple direct comparison.

Logical conjunction

Syntax

bool1 && bool2

Logical AND. Equivalent to if bool1 then bool2 else false.

This operator is strict in bool1, but only evaluates bool2 if bool1 is true.

Example

nix
true && false
=> false

false && throw "never evaluated"
=> false

Logical disjunction

Syntax

bool1 || bool2

Logical OR. Equivalent to if bool1 then true else bool2.

This operator is strict in bool1, but only evaluates bool2 if bool1 is false.

Example

nix
true || false
=> true

true || throw "never evaluated"
=> true

Precedence and disjunctive normal form

The precedence of && and || aligns with disjunctive normal form.
Without parentheses, an expression describes multiple "permissible situations" (connected by ||), where each situation consists of multiple simultaneous conditions (connected by &&).

For example, A || B && C || D && E is parsed as A || (B && C) || (D && E), describing three permissible situations: A holds, or both B and C hold, or both D and E hold.

Logical implication

Syntax

bool1 -> bool2

Logical implication. Equivalent to !bool1 || bool2 (or if bool1 then bool2 else true).

This operator is strict in bool1, but only evaluates bool2 if bool1 is true.

Example

nix
true -> false
=> false

false -> throw "never evaluated"
=> true

Pipe operators

  • a |> b is equivalent to b a
  • a <| b is equivalent to a b

Example

text
nix-repl> 1 |> builtins.add 2 |> builtins.mul 3
9

nix-repl> builtins.add 1 <| builtins.mul 2 <| 3
7

Warning

This syntax is part of an
experimental feature
and may change in future releases.

To use this syntax, make sure the
pipe-operators experimental feature
is enabled.
For example, include the following in nix.conf:

text
extra-experimental-features = pipe-operators

Doc Manual Source Language Scope (`doc/manual/source/language/scope.md`)

Scoping rules

A scope in the Nix language is a dictionary keyed by name, mapping each name to an expression and a definition type.
The definition type is either explicit or implicit.
Each entry in this dictionary is a definition.

Explicit definitions are created by the following expressions:

Implicit definitions are only created by with-expressions.

Every expression is enclosed by a scope.
The outermost expression is enclosed by the built-in, global scope, which contains only explicit definitions.
The expressions listed above extend their enclosing scope by adding new definitions, or replacing existing ones with the same name.
An explicit definition can replace a definition of any type; an implicit definition can only replace another implicit definition.

Each of the above expressions defines which of its subexpressions are enclosed by the extended scope.
In all other cases, the same scope that encloses an expression is the enclosing scope for its subexpressions.

The Nix language is statically scoped;
the value of a variable is determined only by the variable's enclosing scope, and not by the dynamic context in which the variable is evaluated.

Note

Expressions entered into the Nix REPL are enclosed by a scope that can be extended by command line arguments or previous REPL commands.
These ways of extending scope are not, strictly speaking, part of the Nix language.


Doc Manual Source Language String Context (`doc/manual/source/language/string-context.md`)

String context

Note

This is an advanced topic.
The Nix language is designed to be used without the programmer consciously dealing with string contexts or even knowing what they are.

A string in the Nix language is not just a sequence of characters like strings in other languages.
It is actually a pair of a sequence of characters and a string context.
The string context is an (unordered) set of string context elements.

The purpose of string contexts is to collect non-string values attached to strings via
string concatenation,
string interpolation,
and similar operations.
The idea is that a user can reference other files when creating text files through Nix expressions, without manually keeping track of the exact paths.
Nix will ensure that the all referenced files are accessible – that all store paths are valid.

Note

String contexts are not explicitly manipulated in idiomatic Nix language code.

String context elements come in different forms:

  • deriving path{#string-context-element-derived-path}

    A string context element of this type is a deriving path.
    They can be either of type constant or output, which correspond to the types of deriving paths.

    • [Constant string context elements]{#string-context-constant}

      Example

      builtins.storePath creates a string with a single constant string context element:

      nix
      builtins.getContext (builtins.storePath "/nix/store/ikwkxz4wwlp2g1428n7dy729cg1d9hin-hello-2.10")

      evaluates to

      nix
      {
        "/nix/store/ikwkxz4wwlp2g1428n7dy729cg1d9hin-hello-2.10" = {
          path = true;
        };
      }
    • [Output string context elements]{#string-context-output}

      Example

      The behavior of string contexts are best demonstrated with a built-in function that is still experimental: builtins.outputOf.
      This example will not work with stable Nix!

      nix
      builtins.getContext
        (builtins.outputOf
          (builtins.storePath "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv")
          "out")

      evaluates to

      nix
      {
        "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv" = {
          outputs = [ "out" ];
        };
      }
  • [derivation deep]{#string-context-element-derivation-deep}

    derivation deep is an advanced feature intended to be used with the
    exportReferencesGraph derivation attribute.
    A derivation deep string context element is a derivation path, and refers to both its outputs and the entire build closure of that derivation:
    all its outputs, all the other derivations the given derivation depends on, and all the outputs of those.

    Example

    The best way to illustrate derivation deep string contexts is with builtins.addDrvOutputDependencies.
    Take a regular constant string context element pointing to a derivation, and transform it into a "Derivation deep" string context element.

    nix
    builtins.getContext
      (builtins.addDrvOutputDependencies
        (builtins.storePath "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv"))

    evaluates to

    nix
    {
      "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv" = {
        allOutputs = true;
      };
    }

Inspecting string contexts

Most basically, builtins.hasContext will tell whether a string has a non-empty context.

When more granular information is needed, builtins.getContext can be used.
It creates an attribute set representing the string context, which can be inspected as usual.

Clearing string contexts

builtins.unsafeDiscardStringContext will make a copy of a string, but with an empty string context.
The returned string can be used in more ways, e.g. by operators that require the string context to be empty.
The requirement to explicitly discard the string context in such use cases helps ensure that string context elements are not lost by mistake.
The "unsafe" marker is only there to remind that Nix normally guarantees that dependencies are tracked, whereas the returned string has lost them.

Constructing string contexts

builtins.appendContext will create a copy of a string, but with additional string context elements.
The context is specified explicitly by an attribute set in the format that builtins.hasContext produces.
A string with arbitrary contexts can be made like this:

  1. Create a string with the desired string context elements.
    (The contents of the string do not matter.)
  2. Dump its context with builtins.getContext.
  3. Combine it with a base string and repeated builtins.appendContext calls.

Doc Manual Source Language String Interpolation (`doc/manual/source/language/string-interpolation.md`)

String interpolation

String interpolation is a language feature where a string, path, or attribute name can contain expressions enclosed in ${ } (dollar-sign with curly brackets).

Such a construct is called interpolated string, and the expression inside is an interpolated expression.

Syntax

interpolation_element → ${ expression }

Examples

String

Rather than writing

nix
"--with-freetype2-library=" + freetype + "/lib"

(where freetype is a derivation expression), you can instead write

nix
"--with-freetype2-library=${freetype}/lib"

The latter is automatically translated to the former.

A more complicated example (from the Nix expression for Qt):

nix
configureFlags = "
  -system-zlib -system-libpng -system-libjpeg
  ${if openglSupport then "-dlopen-opengl
    -L${mesa}/lib -I${mesa}/include
    -L${libXmu}/lib -I${libXmu}/include" else ""}
  ${if threadSupport then "-thread" else "-no-thread"}
";

Note that Nix expressions and strings can be arbitrarily nested;
in this case the outer string contains various interpolated expressions that themselves contain strings (e.g., "-thread"), some of which in turn contain interpolated expressions (e.g., ${mesa}).

To write a literal ${ in an regular string, escape it with a backslash (\).

Example

nix
"echo \${PATH}"
text
"echo ${PATH}"

To write a literal ${ in an indented string, escape it with two single quotes ('').

Example

nix
''
  echo ''${PATH}
''
text
"echo ${PATH}\n"

$${ can be written literally in any string.

Example

In Make, $ in file names or recipes is represented as $$, see GNU make: Basics of Variable Reference.
This can be expressed directly in the Nix language strings:

nix
''
  MAKEVAR = Hello
  all:
  	@export BASHVAR=world; echo $(MAKEVAR) $${BASHVAR}
''
text
"MAKEVAR = Hello\nall:\n\t@export BASHVAR=world; echo $(MAKEVAR) $\${BASHVAR}\n"

See the documentation on strings for details.

Path

Rather than writing

nix
./. + "/" + foo + "-" + bar + ".nix"

or

nix
./. + "/${foo}-${bar}.nix"

you can instead write

nix
./${foo}-${bar}.nix

Attribute name

Attribute names can be interpolated strings.

Example

nix
let name = "foo"; in
{ ${name} = 123; }
text
{ foo = 123; }

Attributes can be selected with interpolated strings.

Example

nix
let name = "foo"; in
{ foo = 123; }.${name}
text
123

Interpolated expression

An expression that is interpolated must evaluate to one of the following:

A string interpolates to itself.

A path in an interpolated expression is first copied into the Nix store, and the resulting string is the store path of the newly created store object.

Example

console
$ mkdir foo

Reference the empty directory in an interpolated expression:

nix
"${./foo}"
text
"/nix/store/2hhl2nz5v0khbn06ys82nrk99aa1xxdw-foo"

A derivation interpolates to the store path of its first output.

Example

nix
let
  pkgs = import <nixpkgs> {};
in
"${pkgs.hello}"
text
"/nix/store/qnlr7906z0mrl2syrkdbpicffq02nw07-hello-2.12.1"

An attribute set interpolates to the return value of the function in the __toString applied to the attribute set itself.

Example

nix
let
  a = {
    value = 1;
    __toString = self: toString (self.value + 1);
  };
in
"${a}"
text
"2"

An attribute set also interpolates to the value of its outPath attribute.

Example

nix
let
  a = { outPath = "foo"; };
in
"${a}"
text
"foo"

If both __toString and outPath are present in an attribute set, __toString takes precedence.

Example

nix
let
  a = { __toString = _: "yes"; outPath = throw "no"; };
in
"${a}"
text
"yes"

If neither is present, an error is thrown.

Example

nix
let
  a = {};
in
"${a}"
text
error: cannot coerce a set to a string: { }

       at «string»:4:2:

            3| in
            4| "${a}"
             |  ^

Doc Manual Source Language String Literals (`doc/manual/source/language/string-literals.md`)

String literals

A string literal represents a string value.

Syntax

expression → string

string → " ( string_char* interpolation_element )* string_char* "

string → '' ( indented_string_char* interpolation_element )* indented_string_char* ''

string → uri

string_char ~ [^"$\\]|\$(?!\{)|\\.

indented_string_char ~ [^$']|\$\$|\$(?!\{)|''[$']|''\\.|'(?!')

uri ~ [A-Za-z][+\-.0-9A-Za-z]*:[!$%&'*+,\-./0-9:=?@A-Z_a-z~]+

Strings can be written in three ways.

The most common way is to enclose the string between double quotes, e.g., "foo bar".
Strings can span multiple lines.
The results of other expressions can be included into a string by enclosing them in ${ }, a feature known as string interpolation.

The following must be escaped to represent them within a string, by prefixing with a backslash (\):

  • Double quote (")

Example

nix
"\""
text
"\""
  • Backslash (\)

Example

nix
"\\"
text
"\\"
  • Dollar sign followed by an opening curly bracket (${) – "dollar-curly"

Example

nix
"\${"
text
"\${"

The newline, carriage return, and tab characters can be written as \n, \r and \t, respectively.

A "double-dollar-curly" ($${) can be written literally.

Example

nix
"$${"
text
"$\${"

String values are output on the terminal with Nix-specific escaping.
Strings written to files will contain the characters encoded by the escaping.

The second way to write string literals is as an indented string, which is enclosed between pairs of double single-quotes (''), like so:

nix
''
This is the first line.
This is the second line.
  This is the third line.
''

This kind of string literal intelligently strips indentation from
the start of each line. To be precise, it strips from each line a
number of spaces equal to the minimal indentation of the string as a
whole (disregarding the indentation of empty lines). For instance,
the first and second line are indented two spaces, while the third
line is indented four spaces. Thus, two spaces are stripped from
each line, so the resulting string is

nix
"This is the first line.\nThis is the second line.\n  This is the third line.\n"

Note

Whitespace and newline following the opening '' is ignored if there is no non-whitespace text on the initial line.

Warning

Prefixed tab characters are not stripped.

Example

The following indented string is prefixed with tabs:

''
all:
@echo hello
''

text
"\tall:\n\t\t@echo hello\n"

Indented strings support string interpolation.

The following must be escaped to represent them in an indented string:

  • $ is escaped by prefixing it with two single quotes ('')

Example

nix
''
  ''$
''
text
"$\n"
  • '' is escaped by prefixing it with one single quote (')

Example

nix
''
  '''
''
text
"''\n"

These special characters are escaped as follows:

  • Linefeed (\n): ''\n
  • Carriage return (\r): ''\r
  • Tab (\t): ''\t

''\ escapes any other character.

A "dollar-curly" (${) can be written as follows:

Example

nix
''
  echo ''${PATH}
''
text
"echo ${PATH}\n"

Note

This differs from the syntax for escaping a dollar-curly within double quotes ("\${"). Be aware of which one is needed at a given moment.

A "double-dollar-curly" ($${) can be written literally.

Example

nix
''
  $${
''
text
"$\${\n"

Indented strings are primarily useful in that they allow multi-line
string literals to follow the indentation of the enclosing Nix
expression, and that less escaping is typically necessary for
strings representing languages such as shell scripts and
configuration files because '' is much less common than ".
Example:

nix
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 ""}
  '';
...
}

Finally, as a convenience, URIs as defined in appendix B of
RFC 2396 can be written as
is
, without quotes. For instance, the string
"http://example.org/foo.tar.bz2" can also be written as
http://example.org/foo.tar.bz2.


Doc Manual Source Language Syntax (`doc/manual/source/language/syntax.md`)

Language Constructs

This section covers syntax and semantics of the Nix language.

Basic Literals

String {#string-literal}

See String literals.

Number {#number-literal}

Numbers, which can be integers (like 123) or floating point
(like 123.43 or .27e13).

Integers in the Nix language are 64-bit two's complement signed integers, with a range of -9223372036854775808 to 9223372036854775807, inclusive.

Note that negative numeric literals are actually parsed as unary negation of positive numeric literals.
This means that the minimum integer -9223372036854775808 cannot be written as-is as a literal, since the positive number 9223372036854775808 is one past the maximum range.

See arithmetic and comparison operators for semantics.

Path {#path-literal}

Paths can be expressed by path literals such as ./builder.sh.

A path literal must contain at least one slash to be recognised as such.
For instance, builder.sh is not a path:
it's parsed as an expression that selects the attribute sh from the variable builder.

Path literals are resolved relative to their base directory.
Path literals may also refer to absolute paths by starting with a slash.

Note

Absolute paths make expressions less portable.
In the case where a function translates a path literal into an absolute path string for a configuration file, it is recommended to write a string literal instead.
This avoids some confusion about whether files at that location will be used during evaluation.
It also avoids unintentional situations where some function might try to copy everything at the location into the store.

If the first component of a path is a ~, it is interpreted such that the rest of the path were relative to the user's home directory.
For example, ~/foo would be equivalent to /home/edolstra/foo for a user whose home directory is /home/edolstra.
Path literals that start with ~ are not allowed in pure evaluation.

Path literals can also include string interpolation, besides being interpolated into other expressions.

At least one slash (/) must appear before any interpolated expression for the result to be recognized as a path.

a.${foo}/b.${bar} is a syntactically valid number division operation.
./a.${foo}/b.${bar} is a path.

Lookup path literals such as <nixpkgs> also resolve to path values.

List {#list-literal}

Lists are formed by enclosing a whitespace-separated list of values
between square brackets. For example,

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

defines a list of four elements, the last being the result of a call to
the function f. Note that function calls have to be enclosed in
parentheses. If they had been omitted, e.g.,

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

the result would be a list of five elements, the fourth one being a
function and the fifth being a set.

Note that lists are only lazy in values, and they are strict in length.

Elements in a list can be accessed using builtins.elemAt.

Attribute Set {#attrs-literal}

An attribute set is a collection of name-value-pairs called attributes.

Attribute sets are written enclosed in curly brackets ({ }).
Attribute names and attribute values are separated by an equal sign (=).
Each value can be an arbitrary expression, terminated by a semicolon (;)

An attribute name is a string without context, and is denoted by a name (an identifier or string literal).

Syntax

attrset → { { name = expr ; } }

Attributes can appear in any order.
An attribute name may only occur once in each attribute set.

Example

This defines an attribute set with attributes named:

  • x with the value 123, an integer
  • text with the value "Hello", a string
  • y where the value is the result of applying the function f to the attribute set { bla = 456; }
nix
{
  x = 123;
  text = "Hello";
  y = f { bla = 456; };
}

Attributes in nested attribute sets can be written using attribute paths.

Syntax

attrset → { { attrpath = expr ; } }

An attribute path is a dot-separated list of names.

Syntax

attrpath = name { . name }

Example

nix
{ a.b.c = 1; a.b.d = 2; }
text
{
  a = {
    b = {
      c = 1;
      d = 2;
    };
  };
}

Attribute names can also be set implicitly by using the inherit keyword.

Example

nix
{ inherit (builtins) true; }
text
{ true = true; }

Attributes can be accessed with the . operator.

Example:

nix
{ a = "Foo"; b = "Bar"; }.a

This evaluates to "Foo".

It is possible to provide a default value in an attribute selection using the or keyword.

Example:

nix
{ a = "Foo"; b = "Bar"; }.c or "Xyzzy"
nix
{ a = "Foo"; b = "Bar"; }.c.d.e.f.g or "Xyzzy"

will both evaluate to "Xyzzy" because there is no c attribute in the set.

You can use arbitrary double-quoted strings as attribute names:

nix
{ "$!@#?" = 123; }."$!@#?"
nix
let bar = "bar"; in
{ "foo ${bar}" = 123; }."foo ${bar}"

Both will evaluate to 123.

Attribute names support string interpolation:

nix
let bar = "foo"; in
{ foo = 123; }.${bar}
nix
let bar = "foo"; in
{ ${bar} = 123; }.foo

Both will evaluate to 123.

In the special case where an attribute name inside of a set declaration
evaluates to null (which is normally an error, as null cannot be coerced to
a string), that attribute is simply not added to the set:

nix
{ ${if foo then "bar" else null} = true; }

This will evaluate to {} if foo evaluates to false.

A set that has a [__functor]{#attr-__functor} attribute whose value is callable (i.e. is
itself a function or a set with a __functor attribute whose value is
callable) can be applied as if it were a function, with the set itself
passed in first , e.g.,

nix
let add = { __functor = self: x: x + self.x; };
    inc = add // { x = 1; }; # inc is { x = 1; __functor = (...) }
in inc 1 # equivalent of `add.__functor add 1` i.e. `1 + self.x`

evaluates to 2. This can be used to attach metadata to a function
without the caller needing to treat it specially, or to implement a form
of object-oriented programming, for example.

Recursive sets

Recursive sets are like normal attribute sets, but the attributes can refer to each other.

rec-attrset = rec { [ name = expr ; ]... }

Example:

nix
rec {
  x = y;
  y = 123;
}.x

This evaluates to 123.

Note that without rec the binding x = y; would
refer to the variable y in the surrounding scope, if one exists, and
would be invalid if no such variable exists. That is, in a normal
(non-recursive) set, attributes are not added to the lexical scope; in a
recursive set, they are.

Recursive sets of course introduce the danger of infinite recursion. For
example, the expression

nix
rec {
  x = y;
  y = x;
}.x

will crash with an infinite recursion encountered error message.

Let-expressions

A let-expression allows you to define local variables for an expression.

let-in = let [ identifier = expr ; ]... in expr

Example:

nix
let
  x = "foo";
  y = "bar";
in x + y

This evaluates to "foobar".

There is also another, older, syntax for let expressions that should not be used in new code:

let = let { identifier = expr ; [ identifier = expr ;]... }

In this form, the attribute set between the { } is recursive.

One of the attributes must have the special name body,
which is the result of the expression.

Example:

nix
let {
  foo = bar;
  bar = "baz";
  body = foo;
}

This evaluates to "baz".

Inheriting attributes

When defining an attribute set or in a let-expression it is often convenient to copy variables from the surrounding lexical scope (e.g., when you want to propagate attributes).
This can be shortened using the inherit keyword.

Example:

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

is equivalent to

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

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

Note

This works because x is added to the lexical scope by the let construct.

It is also possible to inherit attributes from another attribute set.

Example:

In this fragment from all-packages.nix,

nix
graphviz = (import ../tools/graphics/graphviz) {
  inherit fetchurl stdenv libpng libjpeg expat x11 yacc;
  inherit (xorg) libXaw;
};

xorg = {
  libX11 = ...;
  libXaw = ...;
  ...
}

libpng = ...;
libjpg = ...;
...

the set used in the function call to the function defined in
../tools/graphics/graphviz inherits a number of variables from the
surrounding scope (fetchurl ... yacc), but also inherits libXaw
(the X Athena Widgets) from the xorg set.

Summarizing the fragment

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

is equivalent to

nix
...
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.

In a let expression, inherit can be used to selectively bring specific attributes of a set into scope. For example

nix
let
  x = { a = 1; b = 2; };
  inherit (builtins) attrNames;
in
{
  names = attrNames x;
}

is equivalent to

nix
let
  x = { a = 1; b = 2; };
in
{
  names = builtins.attrNames x;
}

both evaluate to { names = [ "a" "b" ]; }.

Functions

Functions have the following form:

nix
pattern: body

The pattern specifies what the argument of the function must look like,
and binds variables in the body to (parts of) the argument. There are
three kinds of patterns:

  • If a pattern is a single identifier, then the function matches any
    argument. Example:

    nix
    let negate = x: !x;
        concat = x: y: x + y;
    in if negate true then concat "foo" "bar" else ""

    Note that concat is a function that takes one argument and returns
    a function that takes another argument. This allows partial
    parameterisation (i.e., only filling some of the arguments of a
    function); e.g.,

    nix
    map (concat "foo") [ "bar" "bla" "abc" ]

    evaluates to [ "foobar" "foobla" "fooabc" ].

  • A set pattern of the form { name1, name2, …, nameN } matches a
    set containing the listed attributes, and binds the values of those
    attributes to variables in the function body. For example, the
    function

    nix
    { x, y, z }: z + y + x

    can only be called with a set containing exactly the attributes x,
    y and z. No other attributes are allowed. If you want to allow
    additional arguments, you can use an ellipsis (...):

    nix
    { x, y, z, ... }: z + y + x

    This works on any set that contains at least the three named
    attributes.

  • It is possible to provide default values for attributes, in
    which case they are allowed to be missing. A default value is
    specified by writing name ? e, where e is an arbitrary
    expression. For example,

    nix
    { x, y ? "foo", z ? "bar" }: z + y + x

    specifies a function that only requires an attribute named x, but
    optionally accepts y and z.

  • An @-pattern provides a means of referring to the whole value
    being matched:

    nix
    args@{ x, y, z, ... }: z + y + x + args.a

    but can also be written as:

    nix
    { x, y, z, ... } @ args: z + y + x + args.a

    Here args is bound to the argument as passed, which is further
    matched against the pattern { x, y, z, ... }.
    The @-pattern makes mainly sense with an ellipsis(...) as
    you can access attribute names as a, using args.a, which was
    given as an additional attribute to the function.

    Warning

    args@ binds the name args to the attribute set that is passed to the function.
    In particular, args does not include any default values specified with ? in the function's set pattern.

    For instance

    nix
    let
      f = args@{ a ? 23, ... }: [ a args ];
    in
      f {}

    is equivalent to

    nix
    let
      f = args @ { ... }: [ (args.a or 23) args ];
    in
      f {}

    and both expressions will evaluate to:

    nix
    [ 23 {} ]
  • All bindings introduced by the function are in scope in the entire function expression; not just in the body.
    It can therefore be used in default values.

    Example

    A parameter (x), is used in the default value for another parameter (y):

    nix
    let
      f = { x, y ? [x] }: { inherit y; };
    in
      f { x = 3; }

    This evaluates to:

    nix
    {
      y = [ 3 ];
    }

    Example

    The binding of an @ pattern, args, is used in the default value for a parameter, x:

    nix
    let
      f = args@{ x ? args.a, ... }: x;
    in
      f { a = 1; }

    This evaluates to:

    nix
    1

Note that functions do not have names. If you want to give them a name,
you can bind them to an attribute, e.g.,

nix
let concat = { x, y }: x + y;
in concat { x = "foo"; y = "bar"; }

Conditionals

Conditionals look like this:

nix
if e1 then e2 else e3

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

Assertions

Assertions are generally used to check that certain requirements on or
between features and dependencies hold. They look like this:

nix
assert e1; e2

where e1 is an expression that should evaluate to a Boolean value. If
it evaluates to true, e2 is returned; otherwise expression
evaluation is aborted and a backtrace is printed.

Here is a Nix expression for the Subversion package that shows how
assertions can be used:.

nix
{ localServer ? false
, httpServer ? false
, sslSupport ? false
, pythonBindings ? false
, javaSwigBindings ? false
, javahlBindings ? false
, stdenv, fetchurl
, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null
}:

assert localServer -> db4 != null; ①
assert httpServer -> httpd != null && httpd.expat == expat; ②
assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); ③
assert pythonBindings -> swig != null && swig.pythonSupport;
assert javaSwigBindings -> swig != null && swig.javaSupport;
assert javahlBindings -> j2sdk != null;

stdenv.mkDerivation {
  name = "subversion-1.1.1";
  ...
  openssl = if sslSupport then openssl else null; ④
  ...
}

The points of interest are:

  1. This assertion states that if Subversion is to have support for
    local repositories, then Berkeley DB is needed. So if the Subversion
    function is called with the localServer argument set to true but
    the db4 argument set to null, then the evaluation fails.

    Note that -> is the logical
    implication

    Boolean operation.

  2. This is a more subtle condition: if Subversion is built with Apache
    (httpServer) support, then the Expat library (an XML library) used
    by Subversion should be same as the one used by Apache. This is
    because in this configuration Subversion code ends up being linked
    with Apache code, and if the Expat libraries do not match, a build-
    or runtime link error or incompatibility might occur.

  3. This assertion says that in order for Subversion to have SSL support
    (so that it can access https URLs), an OpenSSL library must be
    passed. Additionally, it says that if Apache support is enabled,
    then Apache's OpenSSL should match Subversion's. (Note that if
    Apache support is not enabled, we don't care about Apache's
    OpenSSL.)

  4. The conditional here is not really related to assertions, but is
    worth pointing out: it ensures that if SSL support is disabled, then
    the Subversion derivation is not dependent on OpenSSL, even if a
    non-null value was passed. This prevents an unnecessary rebuild of
    Subversion if OpenSSL changes.

With-expressions

A with-expression,

nix
with e1; e2

introduces the set e1 into the lexical scope of the expression e2.
For instance,

nix
let as = { x = "foo"; y = "bar"; };
in with as; x + y

evaluates to "foobar" since the with adds the x and y attributes
of as to the lexical scope in the expression x + y. The most common
use of with is in conjunction with the import function. E.g.,

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

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

The bindings introduced by with do not shadow bindings introduced by
other means, e.g.

nix
let a = 3; in with { a = 1; }; let a = 4; in with { a = 2; }; ...

establishes the same scope as

nix
let a = 1; in let a = 2; in let a = 3; in let a = 4; in ...

Variables coming from outer with expressions are shadowed:

nix
with { a = "outer"; };
with { a = "inner"; };
a

Does evaluate to "inner".

Comments

  • Inline comments start with # and run until the end of the line.

    Example

    nix
    # A number
    2 # Equals 1 + 1
    console
    2
  • Block comments start with /* and run until the next occurrence of */.

    Example

    nix
    /*
    Block comments
    can span multiple lines.
    */ "hello"
    console
    "hello"

    This means that block comments cannot be nested.

    Example

    nix
    /* /* nope */ */ 1
    console
    error: syntax error, unexpected '*'
    
           at «string»:1:15:
    
                1| /* /* nope */ *
                 |               ^

    Consider escaping nested comments and unescaping them in post-processing.

    Example

    nix
    /* /* nested *\/ */ 1
    console
    1

Doc Manual Source Language Types (`doc/manual/source/language/types.md`)

Data Types

Every value in the Nix language has one of the following types:

Primitives

Integer {#type-int}

An integer in the Nix language is a signed 64-bit integer.

Non-negative integers can be expressed as integer literals.
Negative integers are created with the arithmetic negation operator.
The function builtins.isInt can be used to determine if a value is an integer.

Float {#type-float}

A float in the Nix language is a 64-bit IEEE 754 floating-point number.

Most non-negative floats can be expressed as float literals.
Negative floats are created with the arithmetic negation operator.
The function builtins.isFloat can be used to determine if a value is a float.

Boolean {#type-bool}

A boolean in the Nix language is one of true or false.

These values are available as attributes of builtins as builtins.true and builtins.false.
The function builtins.isBool can be used to determine if a value is a boolean.

String {#type-string}

A string in the Nix language is an immutable, finite-length sequence of bytes, along with a string context.
Nix does not assume or support working natively with character encodings.

String values without string context can be expressed as string literals.
The function builtins.isString can be used to determine if a value is a string.

Path {#type-path}

A path in the Nix language is an immutable, finite-length sequence of bytes starting with /, representing a POSIX-style, canonical file system path.
Path values are distinct from string values, even if they contain the same sequence of bytes.
Operations that produce paths will simplify the result as the standard C function realpath would, except that there is no symbolic link resolution.

Paths are suitable for referring to local files, and are often preferable over strings.

  • Path values do not contain trailing or duplicate slashes, ., or ...
  • Relative path literals are automatically resolved relative to their base directory.
  • Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.

A file is not required to exist at a given path in order for that path value to be valid, but a path that is converted to a string with string interpolation or string-and-path concatenation must resolve to a readable file or directory which will be copied into the Nix store.
For instance, evaluating "${./foo.txt}" will cause foo.txt from the same directory to be copied into the Nix store and result in the string "/nix/store/<hash>-foo.txt".
Operations such as import can also expect a path to resolve to a readable file or directory.

Note

The Nix language assumes that all input files will remain unchanged while evaluating a Nix expression.
For example, assume you used a file path in an interpolated string during a nix repl session.
Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new store path, since Nix might not re-read the file contents.
Use :r to reset the repl as needed.

Path values can be expressed as path literals.
The function builtins.isPath can be used to determine if a value is a path.

Null {#type-null}

There is a single value of type null in the Nix language.

This value is available as an attribute on the builtins attribute set as builtins.null.

Compound values

Attribute set {#type-attrs}

An attribute set can be constructed with an attribute set literal.
The function builtins.isAttrs can be used to determine if a value is an attribute set.

List {#type-list}

A list can be constructed with a list literal.
The function builtins.isList can be used to determine if a value is a list.

Function {#type-function}

A function can be constructed with a function expression.
The function builtins.isFunction can be used to determine if a value is a function.

External {#type-external}

An external value is an opaque value created by a Nix plugin.
Such a value can be substituted in Nix expressions but only created and used by plugin code.


Doc Manual Source Language Variables (`doc/manual/source/language/variables.md`)

Variables

A variable is an identifier used as an expression.

Syntax

expression → identifier

A variable must have the same name as a definition in the scope that encloses it.
The value of a variable is the value of the corresponding expression in the enclosing scope.


Doc Manual Source Package Management Binary Cache Substituter (`doc/manual/source/package-management/binary-cache-substituter.md`)

Serving a Nix store via HTTP

You can easily share the Nix store of a machine via HTTP. This allows
other machines to fetch store paths from that machine to speed up
installations. It uses the same binary cache mechanism that Nix
usually uses to fetch pre-built binaries from https://cache.nixos.org.

The daemon that handles binary cache requests via HTTP, nix-serve, is
not part of the Nix distribution, but you can install it from Nixpkgs:

console
$ nix-env --install --attr nixpkgs.nix-serve

You can then start the server, listening for HTTP connections on
whatever port you like:

console
$ nix-serve -p 8080

To check whether it works, try fetching the nix-cache-info file on the client:

console
$ curl http://avalon:8080/nix-cache-info
StoreDir: /nix/store
WantMassQuery: 1
Priority: 30

When writing to a binary cache (e.g., with nix copy), Nix creates nix-cache-info automatically if it doesn't exist.

On the client side, you can tell Nix to use your binary cache using
--substituters, e.g.:

console
$ nix-env --install --attr nixpkgs.firefox --substituters http://avalon:8080/

The option substituters tells Nix to use this binary cache in
addition to your default caches, such as https://cache.nixos.org.
Thus, for any path in the closure of Firefox, Nix will first check if
the path is available on the server avalon or another binary caches.
If not, it will fall back to building from source.

You can also tell Nix to always use your binary cache by adding a line
to the nix.conf configuration file like this:

text
substituters = http://avalon:8080/ https://cache.nixos.org/

Doc Manual Source Package Management Garbage Collection (`doc/manual/source/package-management/garbage-collection.md`)

Garbage Collection

nix-env operations such as upgrades (-u) and uninstall (-e) never
actually delete packages from the system. All they do (as shown above)
is to create a new user environment that no longer contains symlinks to
the “deleted” packages.

Of course, since disk space is not infinite, unused packages should be
removed at some point. You can do this by running the Nix garbage
collector. It will remove from the Nix store any package not used
(directly or indirectly) by any generation of any profile.

Note however that as long as old generations reference a package, it
will not be deleted. After all, we wouldn’t be able to do a rollback
otherwise. So in order for garbage collection to be effective, you
should also delete (some) old generations. Of course, this should only
be done if you are certain that you will not need to roll back.

To delete all old (non-current) generations of your current profile:

console
$ nix-env --delete-generations old

Instead of old you can also specify a list of generations, e.g.,

console
$ nix-env --delete-generations 10 11 14

To delete all generations older than a specified number of days (except
the current generation), use the d suffix. For example,

console
$ nix-env --delete-generations 14d

deletes all generations older than two weeks.

After removing appropriate old generations you can run the garbage
collector as follows:

console
$ nix-store --gc

The behaviour of the garbage collector is affected by the
keep-derivations (default: true) and keep-outputs (default: false)
options in the Nix configuration file. The defaults will ensure that all
derivations that are build-time dependencies of garbage collector roots
will be kept and that all output paths that are runtime dependencies
will be kept as well. All other derivations or paths will be collected.
(This is usually what you want, but while you are developing it may make
sense to keep outputs to ensure that rebuild times are quick.) If you
are feeling uncertain, you can also first view what files would be
deleted:

console
$ nix-store --gc --print-dead

Likewise, the option --print-live will show the paths that won’t be
deleted.

There is also a convenient little utility nix-collect-garbage, which
when invoked with the -d (--delete-old) switch deletes all old
generations of all profiles in /nix/var/nix/profiles. So

console
$ nix-collect-garbage -d

is a quick and easy way to clean up your system.


Doc Manual Source Package Management Garbage Collector Roots (`doc/manual/source/package-management/garbage-collector-roots.md`)

Garbage Collector Roots

The roots of the garbage collector are all store paths to which there
are symlinks in the directory prefix/nix/var/nix/gcroots. For
instance, the following command makes the path
/nix/store/d718ef...-foo a root of the collector:

console
$ ln -s /nix/store/d718ef...-foo /nix/var/nix/gcroots/bar

That is, after this command, the garbage collector will not remove
/nix/store/d718ef...-foo or any of its dependencies.

Subdirectories of prefix/nix/var/nix/gcroots are searched
recursively. Symlinks to store paths count as roots. Symlinks to
non-store paths are ignored, unless the non-store path is itself a
symlink to a store path.


Doc Manual Source Package Management Profiles (`doc/manual/source/package-management/profiles.md`)

Profiles

Profiles and user environments are Nix’s mechanism for implementing the
ability to allow different users to have different configurations, and
to do atomic upgrades and rollbacks. To understand how they work, it’s
useful to know a bit about how Nix works. In Nix, packages are stored in
unique locations in the Nix store (typically, /nix/store). For
instance, a particular version of the Subversion package might be stored
in a directory
/nix/store/dpmvp969yhdqs7lm2r1a3gng7pyq6vy4-subversion-1.1.3/, while
another version might be stored in
/nix/store/5mq2jcn36ldlmh93yj1n8s9c95pj7c5s-subversion-1.1.2. The long
strings prefixed to the directory names are cryptographic hashes (to be
precise, 160-bit truncations of SHA-256 hashes encoded in Nix32) of all inputs involved in building the package — sources,
dependencies, compiler flags, and so on. So if two packages differ in
any way, they end up in different locations in the file system, so they
don’t interfere with each other. Here is what a part of a typical Nix
store looks like:

Of course, you wouldn’t want to type

console
$ /nix/store/dpmvp969yhdq...-subversion-1.1.3/bin/svn

every time you want to run Subversion. Of course we could set up the
PATH environment variable to include the bin directory of every
package we want to use, but this is not very convenient since changing
PATH doesn’t take effect for already existing processes. The solution
Nix uses is to create directory trees of symlinks to activated
packages. These are called user environments and they are packages
themselves (though automatically generated by nix-env), so they too
reside in the Nix store. For instance, in the figure above, the user
environment /nix/store/0c1p5z4kda11...-user-env contains a symlink to
just Subversion 1.1.2 (arrows in the figure indicate symlinks). This
would be what we would obtain if we had done

console
$ nix-env --install --attr nixpkgs.subversion

on a set of Nix expressions that contained Subversion 1.1.2.

This doesn’t in itself solve the problem, of course; you wouldn’t want
to type /nix/store/0c1p5z4kda11...-user-env/bin/svn either. That’s why
there are symlinks outside of the store that point to the user
environments in the store; for instance, the symlinks default-42-link
and default-43-link in the example. These are called generations
since every time you perform a nix-env operation, a new user
environment is generated based on the current one. For instance,
generation 43 was created from generation 42 when we did

console
$ nix-env --install --attr nixpkgs.subversion nixpkgs.firefox

on a set of Nix expressions that contained Firefox and a new version of
Subversion.

Generations are grouped together into profiles so that different users
don’t interfere with each other if they don’t want to. For example:

console
$ ls -l /nix/var/nix/profiles/
...
lrwxrwxrwx  1 eelco ... default-42-link -> /nix/store/0c1p5z4kda11...-user-env
lrwxrwxrwx  1 eelco ... default-43-link -> /nix/store/3aw2pdyx2jfc...-user-env
lrwxrwxrwx  1 eelco ... default -> default-43-link

This shows a profile called default. The file default itself is
actually a symlink that points to the current generation. When we do a
nix-env operation, a new user environment and generation link are
created based on the current one, and finally the default symlink is
made to point at the new generation. This last step is atomic on Unix,
which explains how we can do atomic upgrades. (Note that the
building/installing of new packages doesn’t interfere in any way with
old packages, since they are stored in different locations in the Nix
store.)

If you find that you want to undo a nix-env operation, you can just do

console
$ nix-env --rollback

which will just make the current generation link point at the previous
link. E.g., default would be made to point at default-42-link. You
can also switch to a specific generation:

console
$ nix-env --switch-generation 43

which in this example would roll forward to generation 43 again. You can
also see all available generations:

console
$ nix-env --list-generations

You generally wouldn’t have /nix/var/nix/profiles/some-profile/bin in
your PATH. Rather, there is a symlink ~/.nix-profile that points to
your current profile. This means that you should put
~/.nix-profile/bin in your PATH (and indeed, that’s what the
initialisation script /nix/etc/profile.d/nix.sh does). This makes it
easier to switch to a different profile. You can do that using the
command nix-env --switch-profile:

console
$ nix-env --switch-profile /nix/var/nix/profiles/my-profile

$ nix-env --switch-profile /nix/var/nix/profiles/default

These commands switch to the my-profile and default profile,
respectively. If the profile doesn’t exist, it will be created
automatically. You should be careful about storing a profile in another
location than the profiles directory, since otherwise it might not be
used as a root of the garbage collector.

All nix-env operations work on the profile pointed to by
~/.nix-profile, but you can override this using the --profile option
(abbreviation -p):

console
$ nix-env --profile /nix/var/nix/profiles/other-profile --install --attr nixpkgs.subversion

This will not change the ~/.nix-profile symlink.


Doc Manual Source Package Management Sharing Packages (`doc/manual/source/package-management/sharing-packages.md`)

Sharing Packages Between Machines

Sometimes you want to copy a package from one machine to another. Or,
you want to install some packages and you know that another machine
already has some or all of those packages or their dependencies. In that
case there are mechanisms to quickly copy packages between machines.


Doc Manual Source Package Management Ssh Substituter (`doc/manual/source/package-management/ssh-substituter.md`)

Serving a Nix store via SSH

You can tell Nix to automatically fetch needed binaries from a remote
Nix store via SSH. For example, the following installs Firefox,
automatically fetching any store paths in Firefox’s closure if they are
available on the server avalon:

console
$ nix-env --install --attr nixpkgs.firefox --substituters ssh://alice@avalon

This works similar to the binary cache substituter that Nix usually
uses, only using SSH instead of HTTP: if a store path P is needed, Nix
will first check if it’s available in the Nix store on avalon. If not,
it will fall back to using the binary cache substituter, and then to
building from source.

Note

The SSH substituter currently does not allow you to enter an SSH
passphrase interactively. Therefore, you should use ssh-add to load
the decrypted private key into ssh-agent.

You can also copy the closure of some store path, without installing it
into your profile, e.g.

console
$ nix-store --realise /nix/store/m85bxg…-firefox-34.0.5 --substituters
ssh://alice@avalon

This is essentially equivalent to doing

console
$ nix-copy-closure --from alice@avalon
/nix/store/m85bxg…-firefox-34.0.5

You can use SSH’s forced command feature to set up a restricted user
account for SSH substituter access, allowing read-only access to the
local Nix store, but nothing more. For example, add the following lines
to sshd_config to restrict the user nix-ssh:

text
Match User nix-ssh
  AllowAgentForwarding no
  AllowTcpForwarding no
  PermitTTY no
  PermitTunnel no
  X11Forwarding no
  ForceCommand nix-store --serve
Match All

On NixOS, you can accomplish the same by adding the following to your
configuration.nix:

nix
nix.sshServe.enable = true;
nix.sshServe.keys = [ "ssh-dss AAAAB3NzaC1k... [email protected]" ];

where the latter line lists the public keys of users that are allowed to
connect.


Doc Manual Source Protocols Derivation Aterm (`doc/manual/source/protocols/derivation-aterm.md`)

Derivation "ATerm" file format

For historical reasons, store derivations are stored on-disk in "Annotated Term" (ATerm) format
(guide,
paper).

Only a small fragment of ATerm is used: the constructors below, string literals, lists, and tuples.

The ATerm format used

Derivations are serialised in one of the following formats:

  • text
    Derive(...)

    For all stable derivations.

  • text
    DrvWithVersion(<version-string>, ...)

    The only version-strings that are in use today are for experimental features:

Grammar

ebnf
derivation = "Derive(" fields ")"
           | "DrvWithVersion(" version "," fields ")" ;

fields = outputs "," input-drvs "," input-srcs ","
         platform "," builder "," args "," env ;

outputs    = "[" [ output { "," output } ] "]" ;
output     = "(" output-name "," output-path "," hash-algo "," hash ")" ;

input-drvs = "[" [ input-drv { "," input-drv } ] "]" ;
input-drv  = "(" drv-path "," input-drv-node ")" ;

input-srcs = "[" [ store-path { "," store-path } ] "]" ;

builder    = string ;
args       = "[" [ string { "," string } ] "]" ;

env        = "[" [ env-entry { "," env-entry } ] "]" ;
env-entry  = "(" string "," string ")" ;

The leaves are all double-quoted, but fall into two kinds.

ebnf
(* may contain escape sequences *)
string      = '"' { char | escape } '"' ;

(* drawn from restricted alphabets, so never escaped *)
verbatim    = '"' { char } '"' ;

(* Not an alternation but a parameter of the grammar: the store
   directory fixes which one holds, for the whole file at once.
   See the note below. *)
store-path  = ? verbatim under a Unix store directory,
                string under a Windows one ? ;

drv-path    = store-path ; (* a store path whose name ends in ".drv" *)
output-path = store-path | '""' ;
output-name = verbatim ;
platform    = verbatim ;
version     = verbatim ;

hash-algo     = '"' [ method-prefix ] algorithm '"' | '""' ;
method-prefix = "r:" | "text:" | "git:" ;      (* flat has none *)
algorithm     = "blake3" | "md5" | "sha1" | "sha256" | "sha512" ;

hash        = '"' hex-digit { hex-digit } '"' | '""' | '"impure"' ;

A store-path is a store path written in full, store directory included.

Note that the derivation name does not appear anywhere.
It is taken from the store path of the derivation, and so must be supplied out-of-band; see below.

Note

store-path is the one leaf that is not pinned down by the grammar, and the reason is the store directory.
A Unix one, /nix/store, happens to hold no character the format escapes, so the path can be written verbatim.
A Windows one does: C:\ProgramData\nix\store contains backslashes, which must be escaped, making the leaf a string:

text
"C:\\ProgramData\\nix\\store/ib3sh3pcz10wsmavxvkdbayhqivbghlq-foo"

Only the store directory is affected; the / separating it from the rest of the path is a forward slash either way.
Nothing else moves: output-name, platform, version and the two hash fields are drawn from alphabets that never need escaping, whichever store directory is in use.

This is a mode, not a choice made afresh at each store path: one of the two holds throughout a given file, and every store path in it is written that way.
The mode is not recorded in the file and cannot be recovered from the bytes — a verbatim path is also a well-formed string — so it has to be supplied out of band, like the derivation name.
Nix takes it from the store it is reading or writing for, defaulting to the platform it was built for, and then holds the parser to it: under a Unix store directory a store path carrying an escape is rejected rather than accepted as a second spelling of the same path.
That is what keeps the encoding canonical in either case.

Strings

Every leaf above is a double-quoted string.
Within one, " and \ are escaped with a backslash, and newline, carriage return, and tab are written \n, \r, and \t.
Those five are the only escapes there are, and each of those five characters is only ever written escaped; see canonical form.

Fields drawn from restricted alphabets — output names, the platform, and the hash fields — cannot contain any of them, and so are written verbatim.
Store paths are written verbatim too, unless the store directory itself needs escaping; see the note above.

Outputs

Which sort of output is meant is not tagged; it is inferred from which of the three fields are empty.

output-path hash-algo hash output
set empty empty input-addressed
empty empty empty deferred input-addressed
set set set fixed-output content-addressed
empty set empty floating content-addressed
empty set "impure" impure

A deferred output does not use a kind of addressing of its own: it is input-addressed, but its path is not yet known, which happens downstream of a floating content-addressed input.
Nothing gates it.
Floating outputs require ca-derivations and impure ones impure-derivations; a fixed-output one additionally requires dynamic-derivations if its method is text:.

The method-prefix of hash-algo is the content addressing method:

prefix method
(none) Flat
r: Nix Archive
text: Text
git: Git

hash is lowercase, and carries no algorithm prefix of its own — the algorithm is named by hash-algo.

For a fixed-output derivation the output-path is redundant — it is a function of the content address — but it must still agree with it.
Two derivations that mean the same thing would otherwise have different encodings, and so different store paths.

Input derivations

Each entry pairs the store path of an input derivation with the outputs of it that are used:

ebnf
input-drv-node = output-names ;
output-names   = "[" [ output-name { "," output-name } ] "]" ;

In the DrvWithVersion("xp-dyn-drv", ...) form
— which requires the dynamic-derivations experimental feature —
a node may instead nest, to name an output of a derivation that is itself an output of a derivation:

ebnf
input-drv-node = output-names
               | "(" output-names "," "[" [ child { "," child } ] "]" ")" ;
child          = "(" output-name "," input-drv-node ")" ;

Canonical form

The encoding is meant to be canonical: each derivation has exactly one.
This matters because the bytes are hashed, both to content-address the derivation itself and to compute input-addressed output paths, so two spellings of the same derivation would be two different derivations.

Accordingly:

  • Outputs, input derivations, input sources, and environment variables appear in ascending order of their keys, with no duplicates.
    The same holds of the output-names naming which outputs of an input derivation are used.

  • A character that can be escaped must be escaped, and no other escape sequence is valid.
    Both halves matter: a literal newline byte inside a string, and \q, are each a second way to write something that already has a spelling.

  • The fields drawn from restricted alphabets — output names and the platform — contain no escape sequences at all, since an escape there would be a second encoding of the same value rather than a necessary one.
    Store paths are held to the same rule, except where the store directory needs escaping, in which case the escapes are the necessary kind.

  • Store paths are written in their canonical form, and the key of an inputDrvs entry is a derivation path, ending in .drv.

  • There is no trailing content after the closing parenthesis.

One exception is known.
The JSON held in the __json environment variable of a derivation using structured attributes is not required to be canonical JSON.
It must instead be preserved verbatim rather than reserialised.
Since the bytes are hashed, whatever encoding a derivation happens to carry is part of its identity.
Re-emitting it — even as equivalent JSON — would change the derivation.

Note

This is not because canonicity is unwanted here, but because there is no settled notion of it to require.
"Canonical JSON" has several competing definitions, disagreeing on key ordering, number representation, and Unicode escaping.
It is also technically fraught:
for example, without hex literals for floating point, number representation is barely tractable.
Structured attributes have been in the wild for many years, so any such choice would also have to reckon with the encodings already out there.
Committing to one of them is therefore not a choice we are yet in a position to make with this format.

Masked derivations {#input-address-encoding}

An input-addressed output path is computed by hashing the ATerm representation of a derivation that has been masked first: parts of it are blanked out before hashing, so that derivations differing only in what was blanked hash alike.

Their encoding differs from the grammar above in two productions:

ebnf
masked-derivation   = "Derive(" fields ")" ;

input-drv           = "(" drv-hash "," output-names ")" ;
drv-hash            = verbatim ;   (* lowercase hexadecimal *)

That is:

  • There is no version header.
    A masked derivation is only ever constructed once dynamic derivations have been resolved away, so it never needs one, and DrvWithVersion(...) does not occur.

  • An inputDrvs key is a hash rather than a store path, and its node is always the flat output-names — the nested form the dynamic-derivations version allows cannot appear, for the same reason.

See input addressing for how those hashes are derived and why; in short, they identify an input derivation up to what it produces rather than how, so that changing where a fixed-output input is fetched from does not change anything downstream.

Replacing the input derivation paths with hashes like this is input masking, and is performed on all derivations.

Whether the outputs carry their paths depends on what is being hashed.
When computing a derivation's own output paths they are output masked too — output-path, and the environment variable named after each output, are empty — since those paths are what is being computed; the result is fully masked.
When hashing a derivation to stand in for it as an input to another, they are left as they are, and the result is input-masked only.

The result is not a derivation that can be built, written to the store, or read back by parse: its inputs name hashes, not paths.
It exists only to be hashed.

Use for encoding to store object

When derivation is encoded to a store object we make the following choices:

  • The store path name is the derivation name with .drv suffixed at the end

    Indeed, the ATerm format above does not contain the name of the derivation, on the assumption that a store path will also be provided out-of-band.

  • The derivation is content-addressed using the "Text" method of content-addressing derivations

Currently we always encode derivations to store object using the ATerm format (and the previous two choices),
but we reserve the option to encode new sorts of derivations differently in the future.


Doc Manual Source Protocols Nix32 (`doc/manual/source/protocols/nix32.md`)

Nix32 Encoding

Nix32 is Nix's variant of Base32 encoding, used for store path digests, hash output via nix hash, and the outputHash derivation attribute.

Alphabet

The Nix32 alphabet consists of these 32 characters:

text
0 1 2 3 4 5 6 7 8 9 a b c d f g h i j k l m n p q r s v w x y z

The letters e, o, u, and t are omitted.

Byte Order

Nix32 encoding processes the hash bytes from the end (last byte first), while base-16 encoding processes from the beginning (first byte first).

Consequently, the string sort order is determined primarily by the first bytes for base-16, and by the last bytes for Nix32.


Doc Manual Source Protocols Store Path (`doc/manual/source/protocols/store-path.md`)

Complete Store Path Calculation

This is the complete specification for how store paths are calculated.

The format of this specification is close to Extended Backus–Naur form, but must deviate for a few things such as hash functions which we treat as bidirectional for specification purposes.

Regular users do not need to know this information --- store paths can be treated as black boxes computed from the properties of the store objects they refer to.
But for those interested in exactly how Nix works, e.g. if they are reimplementing it, this information can be useful.

Store path proper

ebnf
store-path = store-dir "/" digest "-" name

where

  • name = the name of the store object.

  • store-dir = the path of the store directory

  • digest = Nix32 representation of the compressed to 160 bits SHA-256 hash of fingerprint.

    For the definition of the hash compression algorithm, please refer to section 5.1 of the Nix thesis.

Fingerprint

  • ebnf
    fingerprint = type ":sha256:" inner-digest ":" store ":" name

    Note that it includes the location of the store as well as the name to make sure that changes to either of those are reflected in the hash
    (e.g. you won't get /nix/store/<digest>-name1 and /nix/store/<digest>-name2, or /gnu/store/<digest>-name1, with equal hash parts).

  • type = one of:

    • ebnf
      | "text" { ":" store-path }

      This is for the
      "Text"
      method of content addressing store objects.
      The optional trailing store paths are the references of the store object.

    • ebnf
      | "source" { ":" store-path } [ ":self" ]

      This is for the
      "Nix Archive"
      method of content addressing store objects,
      if the hash algorithm is SHA-256.
      Just like in the "Text" case, we can have the store objects referenced by their paths.
      Additionally, we can have an optional :self label to denote self-reference.

    • ebnf
      | "output:" id

      For either the outputs built from derivations,
      or content-addressed store objects that are not using one of the two above cases.
      To be explicit about the latter, that is currently these methods:

      id is the name of the output (usually, "out").
      For content-addressed store objects, id, is always "out".

  • inner-digest = base-16 representation of a SHA-256 hash of inner-fingerprint.
    The base-16 encoding uses lower-cased hex digits.

Inner fingerprint

  • inner-fingerprint = one of the following based on type:

    • if type = "text:" ...:

      the string written to the resulting store path.

    • if type = "source:" ...:

      the Nix Archive (NAR) serialization of the file system object of the store object.

    • if type = "output:" id:

      • For input-addressed derivation outputs:

        the ATerm serialization of the "fully masked derivation", in which fixed-output inputs are replaced by their content addresses and the derivation's own output paths are blanked.

      • For content-addressed store paths:

        ebnf
        "fixed:out:" rec algo ":" hash ":"

        where

        • rec = one of:

          • ebnf
            | ""

            (empty string) for hashes of the flat (single file) serialization

          • ebnf
            | "r:"

            hashes of the for Nix Archive (NAR) (arbitrary file system object) serialization

          • ebnf
            | "git:"

            hashes of the Git blob/tree Merkel tree format

        • ebnf
          algo = "md5" | "sha1" | "sha256"
        • hash = base-16 representation of the path or flat hash of the contents of the path (or expected contents of the path for fixed-output derivations).

        Note that id = "out", regardless of the name part of the store path.
        Also note that NAR + SHA-256 must not use this case, and instead must use the type = "source:" ... case.

Historical Note

The type = "source:" ... and type = "output:out" grammars technically overlap in purpose,
in that both can represent data hashed by its SHA-256 NAR serialization.

The original reason for this way of computing names was to prevent name collisions (for security).
For instance, the thinking was that it shouldn't be feasible to come up with a derivation whose output path collides with the path for a copied source.
The former would have an inner-fingerprint starting with output:out:, while the latter would have an inner-fingerprint starting with source:.

Since 64519cfd657d024ae6e2bb74cb21ad21b886fd2a (2008), however, it was decided that separating derivation-produced vs manually-hashed content-addressed data like this was not useful.
Now, data that is content-addressed with SHA-256 + NAR-serialization always uses the source:... construction, regardless of how it was produced (manually or by derivation).
This allows freely switching between using fixed-output derivations for fetching, and fetching out-of-band and then manually adding.
It also removes the ambiguity from the grammar.


Doc Manual Source Protocols Tarball Fetcher (`doc/manual/source/protocols/tarball-fetcher.md`)

Lockable HTTP Tarball Protocol

Tarball flakes can be served as regular tarballs via HTTP or the file
system (for file:// URLs). Unless the server implements the Lockable
HTTP Tarball protocol, it is the responsibility of the user to make sure that
the URL always produces the same tarball contents.

An HTTP server can return an "immutable" HTTP URL appropriate for lock
files. This allows users to specify a tarball flake input in
flake.nix that requests the latest version of a flake
(e.g. https://example.org/hello/latest.tar.gz), while flake.lock
will record a URL whose contents will not change
(e.g. https://example.org/hello/<revision>.tar.gz). To do so, the
server must return an HTTP Link header with the rel attribute set to
immutable, as follows:

text
Link: <flakeref>; rel="immutable"

(Note the required < and > characters around flakeref.)

flakeref must be a tarball flakeref. It can contain the tarball flake attributes
narHash, rev, revCount and lastModified. If narHash is included, its
value must be the NAR hash of the unpacked tarball (as computed via
nix hash path). Nix checks the contents of the returned tarball
against the narHash attribute. The rev and revCount attributes
are useful when the tarball flake is a mirror of a fetcher type that
has those attributes, such as Git or GitHub. They are not checked by
Nix.

text
Link: <https://example.org/hello/442793d9ec0584f6a6e82fa253850c8085bb150a.tar.gz
  ?rev=442793d9ec0584f6a6e82fa253850c8085bb150a
  &revCount=835
  &narHash=sha256-GUm8Uh/U74zFCwkvt9Mri4DSM%2BmHj3tYhXUkYpiv31M%3D>; rel="immutable"

(The linebreaks in this example are for clarity and must not be included in the actual response.)

For tarball flakes, the value of the lastModified flake attribute is
defined as the timestamp of the newest file inside the tarball.

Gitea and Forgejo support

This protocol is supported by Gitea since v1.22.1 and by Forgejo since v7.0.4/v8.0.0 and can be used with the following flake URL schema:

text
https://<domain name>/<owner>/<repo>/archive/<reference or revision>.tar.gz

Example

nix
# flake.nix
{
   inputs = {
     foo.url = "https://gitea.example.org/some-person/some-flake/archive/main.tar.gz";
     bar.url = "https://gitea.example.org/some-other-person/other-flake/archive/442793d9ec0584f6a6e82fa253850c8085bb150a.tar.gz";
     qux = {
       url = "https://forgejo.example.org/another-person/some-non-flake-repo/archive/development.tar.gz";
       flake = false;
     };
   };
   outputs = { foo, bar, qux }: { /* ... */ };
}
text
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive

---

### Doc Manual Source Release Notes Rl 0.10.1 (`doc/manual/source/release-notes/rl-0.10.1.md`)

# Release 0.10.1 (2006-10-11)

This release fixes two somewhat obscure bugs that occur when evaluating
Nix expressions that are stored inside the Nix store (`NIX-67`). These
do not affect most users.

---

### Doc Manual Source Release Notes Rl 0.10 (`doc/manual/source/release-notes/rl-0.10.md`)

# Release 0.10 (2006-10-06)

> **Note**
> 
> This version of Nix uses Berkeley DB 4.4 instead of 4.3. The database
> is upgraded automatically, but you should be careful not to use old
> versions of Nix that still use Berkeley DB 4.3. In particular, if you
> use a Nix installed through Nix, you should run
> 
>     $ nix-store --clear-substitutes
> 
> first.

> **Warning**
> 
> Also, the database schema has changed slighted to fix a performance
> issue (see below). When you run any Nix 0.10 command for the first
> time, the database will be upgraded automatically. This is
> irreversible.

  - `nix-env` usability improvements:
    
      - An option `--compare-versions` (or `-c`) has been added to
        `nix-env
                                                        --query` to allow you to compare installed versions of packages
        to available versions, or vice versa. An easy way to see if you
        are up to date with what’s in your subscribed channels is
        `nix-env -qc \*`.
    
      - `nix-env --query` now takes as arguments a list of package names
        about which to show information, just like `--install`, etc.:
        for example, `nix-env -q gcc`. Note that to show all
        derivations, you need to specify `\*`.
    
      - `nix-env -i
                                                        pkgname` will now install the highest available version of
        *pkgname*, rather than installing all available versions (which
        would probably give collisions) (`NIX-31`).
    
      - `nix-env (-i|-u) --dry-run` now shows exactly which missing
        paths will be built or substituted.
    
      - `nix-env -qa --description` shows human-readable descriptions of
        packages, provided that they have a `meta.description` attribute
        (which most packages in Nixpkgs don’t have yet).

  - New language features:
    
      - Reference scanning (which happens after each build) is much
        faster and takes a constant amount of memory.
    
      - String interpolation. Expressions like
        
            "--with-freetype2-library=" + freetype + "/lib"
        
        can now be written as
        
            "--with-freetype2-library=${freetype}/lib"
        
        You can write arbitrary expressions within `${...}`, not just
        identifiers.
    
      - Multi-line string literals.
    
      - String concatenations can now involve derivations, as in the
        example `"--with-freetype2-library="
                                                        + freetype + "/lib"`. This was not previously possible because
        we need to register that a derivation that uses such a string is
        dependent on `freetype`. The evaluator now properly propagates
        this information. Consequently, the subpath operator (`~`) has
        been deprecated.
    
      - Default values of function arguments can now refer to other
        function arguments; that is, all arguments are in scope in the
        default values (`NIX-45`).
    
      - Lots of new built-in primitives, such as functions for list
        manipulation and integer arithmetic. See the manual for a
        complete list. All primops are now available in the set
        `builtins`, allowing one to test for the availability of primop
        in a backwards-compatible way.
    
      - Real let-expressions: `let x = ...;
                                                        ... z = ...; in ...`.

  - New commands `nix-pack-closure` and `nix-unpack-closure` than can be
    used to easily transfer a store path with all its dependencies to
    another machine. Very convenient whenever you have some package on
    your machine and you want to copy it somewhere else.

  - XML support:
    
      - `nix-env -q --xml` prints the installed or available packages in
        an XML representation for easy processing by other tools.
    
      - `nix-instantiate --eval-only
                                                        --xml` prints an XML representation of the resulting term. (The
        new flag `--strict` forces ‘deep’ evaluation of the result,
        i.e., list elements and attributes are evaluated recursively.)
    
      - In Nix expressions, the primop `builtins.toXML` converts a term
        to an XML representation. This is primarily useful for passing
        structured information to builders.

  - You can now unambiguously specify which derivation to build or
    install in `nix-env`, `nix-instantiate` and `nix-build` using the
    `--attr` / `-A` flags, which takes an attribute name as argument.
    (Unlike symbolic package names such as `subversion-1.4.0`, attribute
    names in an attribute set are unique.) For instance, a quick way to
    perform a test build of a package in Nixpkgs is `nix-build
            pkgs/top-level/all-packages.nix -A
            foo`. `nix-env -q
            --attr` shows the attribute names corresponding to each derivation.

  - If the top-level Nix expression used by `nix-env`, `nix-instantiate`
    or `nix-build` evaluates to a function whose arguments all have
    default values, the function will be called automatically. Also, the
    new command-line switch `--arg
            name
            value` can be used to specify function arguments on the command
    line.

  - `nix-install-package --url
            URL` allows a package to be installed directly from the given URL.

  - Nix now works behind an HTTP proxy server; just set the standard
    environment variables `http_proxy`, `https_proxy`, `ftp_proxy` or
    `all_proxy` appropriately. Functions such as `fetchurl` in Nixpkgs
    also respect these variables.

  - `nix-build -o
            symlink` allows the symlink to the build result to be named
    something other than `result`.

  - Platform support:
    
      - Support for 64-bit platforms, provided a [suitably patched ATerm
        library](http://bugzilla.sen.cwi.nl:8080/show_bug.cgi?id=606) is
        used. Also, files larger than 2 GiB are now supported.
    
      - Added support for Cygwin (Windows, `i686-cygwin`), Mac OS X on
        Intel (`i686-darwin`) and Linux on PowerPC (`powerpc-linux`).
    
      - Users of SMP and multicore machines will appreciate that the
        number of builds to be performed in parallel can now be
        specified in the configuration file in the `build-max-jobs`
        setting.

  - Garbage collector improvements:
    
      - Open files (such as running programs) are now used as roots of
        the garbage collector. This prevents programs that have been
        uninstalled from being garbage collected while they are still
        running. The script that detects these additional runtime roots
        (`find-runtime-roots.pl`) is inherently system-specific, but it
        should work on Linux and on all platforms that have the `lsof`
        utility.
    
      - `nix-store --gc` (a.k.a. `nix-collect-garbage`) prints out the
        number of bytes freed on standard output. `nix-store
                                                        --gc --print-dead` shows how many bytes would be freed by an
        actual garbage collection.
    
      - `nix-collect-garbage -d` removes all old generations of *all*
        profiles before calling the actual garbage collector (`nix-store
                                                        --gc`). This is an easy way to get rid of all old packages in
        the Nix store.
    
      - `nix-store` now has an operation `--delete` to delete specific
        paths from the Nix store. It won’t delete reachable
        (non-garbage) paths unless `--ignore-liveness` is specified.

  - Berkeley DB 4.4’s process registry feature is used to recover from
    crashed Nix processes.

  - A performance issue has been fixed with the `referer` table, which
    stores the inverse of the `references` table (i.e., it tells you
    what store paths refer to a given path). Maintaining this table
    could take a quadratic amount of time, as well as a quadratic amount
    of Berkeley DB log file space (in particular when running the
    garbage collector) (`NIX-23`).

  - Nix now catches the `TERM` and `HUP` signals in addition to the
    `INT` signal. So you can now do a `killall
            nix-store` without triggering a database recovery.

  - `bsdiff` updated to version 4.3.

  - Substantial performance improvements in expression evaluation and
    `nix-env -qa`, all thanks to [Valgrind](http://valgrind.org/).
    Memory use has been reduced by a factor 8 or so. Big speedup by
    memoisation of path hashing.

  - Lots of bug fixes, notably:
    
      - Make sure that the garbage collector can run successfully when
        the disk is full (`NIX-18`).
    
      - `nix-env` now locks the profile to prevent races between
        concurrent `nix-env` operations on the same profile (`NIX-7`).
    
      - Removed misleading messages from `nix-env -i` (e.g.,
        ``installing
                                                        `foo'`` followed by ``uninstalling
                                                        `foo'``) (`NIX-17`).

  - Nix source distributions are a lot smaller now since we no longer
    include a full copy of the Berkeley DB source distribution (but only
    the bits we need).

  - Header files are now installed so that external programs can use the
    Nix libraries.

---

### Doc Manual Source Release Notes Rl 0.11 (`doc/manual/source/release-notes/rl-0.11.md`)

# Release 0.11 (2007-12-31)

Nix 0.11 has many improvements over the previous stable release. The
most important improvement is secure multi-user support. It also
features many usability enhancements and language extensions, many of
them prompted by NixOS, the purely functional Linux distribution based
on Nix. Here is an (incomplete) list:

  - Secure multi-user support. A single Nix store can now be shared
    between multiple (possible untrusted) users. This is an important
    feature for NixOS, where it allows non-root users to install
    software. The old setuid method for sharing a store between multiple
    users has been removed. Details for setting up a multi-user store
    can be found in the manual.

  - The new command `nix-copy-closure` gives you an easy and efficient
    way to exchange software between machines. It copies the missing
    parts of the closure of a set of store path to or from a remote
    machine via `ssh`.

  - A new kind of string literal: strings between double single-quotes
    (`''`) have indentation “intelligently” removed. This allows large
    strings (such as shell scripts or configuration file fragments in
    NixOS) to cleanly follow the indentation of the surrounding
    expression. It also requires much less escaping, since `''` is less
    common in most languages than `"`.

  - `nix-env` `--set` modifies the current generation of a profile so
    that it contains exactly the specified derivation, and nothing else.
    For example, `nix-env -p /nix/var/nix/profiles/browser --set
            firefox` lets the profile named `browser` contain just Firefox.

  - `nix-env` now maintains meta-information about installed packages in
    profiles. The meta-information is the contents of the `meta`
    attribute of derivations, such as `description` or `homepage`. The
    command `nix-env -q --xml
            --meta` shows all meta-information.

  - `nix-env` now uses the `meta.priority` attribute of derivations to
    resolve filename collisions between packages. Lower priority values
    denote a higher priority. For instance, the GCC wrapper package and
    the Binutils package in Nixpkgs both have a file `bin/ld`, so
    previously if you tried to install both you would get a collision.
    Now, on the other hand, the GCC wrapper declares a higher priority
    than Binutils, so the former’s `bin/ld` is symlinked in the user
    environment.

  - `nix-env -i / -u`: instead of breaking package ties by version,
    break them by priority and version number. That is, if there are
    multiple packages with the same name, then pick the package with the
    highest priority, and only use the version if there are multiple
    packages with the same priority.
    
    This makes it possible to mark specific versions/variant in Nixpkgs
    more or less desirable than others. A typical example would be a
    beta version of some package (e.g., `gcc-4.2.0rc1`) which should not
    be installed even though it is the highest version, except when it
    is explicitly selected (e.g., `nix-env -i
            gcc-4.2.0rc1`).

  - `nix-env --set-flag` allows meta attributes of installed packages to
    be modified. There are several attributes that can be usefully
    modified, because they affect the behaviour of `nix-env` or the user
    environment build script:
    
      - `meta.priority` can be changed to resolve filename clashes (see
        above).
    
      - `meta.keep` can be set to `true` to prevent the package from
        being upgraded or replaced. Useful if you want to hang on to an
        older version of a package.
    
      - `meta.active` can be set to `false` to “disable” the package.
        That is, no symlinks will be generated to the files of the
        package, but it remains part of the profile (so it won’t be
        garbage-collected). Set it back to `true` to re-enable the
        package.

  - `nix-env -q` now has a flag `--prebuilt-only` (`-b`) that causes
    `nix-env` to show only those derivations whose output is already in
    the Nix store or that can be substituted (i.e., downloaded from
    somewhere). In other words, it shows the packages that can be
    installed “quickly”, i.e., don’t need to be built from source. The
    `-b` flag is also available in `nix-env -i` and `nix-env -u` to
    filter out derivations for which no pre-built binary is available.

  - The new option `--argstr` (in `nix-env`, `nix-instantiate` and
    `nix-build`) is like `--arg`, except that the value is a string. For
    example, `--argstr system
            i686-linux` is equivalent to `--arg system
            \"i686-linux\"` (note that `--argstr` prevents annoying quoting
    around shell arguments).

  - `nix-store` has a new operation `--read-log` (`-l`) `paths` that
    shows the build log of the given paths.

  - Nix now uses Berkeley DB 4.5. The database is upgraded
    automatically, but you should be careful not to use old versions of
    Nix that still use Berkeley DB 4.4.

  - The option `--max-silent-time` (corresponding to the configuration
    setting `build-max-silent-time`) allows you to set a timeout on
    builds — if a build produces no output on `stdout` or `stderr` for
    the given number of seconds, it is terminated. This is useful for
    recovering automatically from builds that are stuck in an infinite
    loop.

  - `nix-channel`: each subscribed channel is its own attribute in the
    top-level expression generated for the channel. This allows
    disambiguation (e.g. `nix-env
            -i -A nixpkgs_unstable.firefox`).

  - The substitutes table has been removed from the database. This makes
    operations such as `nix-pull` and `nix-channel --update` much, much
    faster.

  - `nix-pull` now supports bzip2-compressed manifests. This speeds up
    channels.

  - `nix-prefetch-url` now has a limited form of caching. This is used
    by `nix-channel` to prevent unnecessary downloads when the channel
    hasn’t changed.

  - `nix-prefetch-url` now by default computes the SHA-256 hash of the
    file instead of the MD5 hash. In calls to `fetchurl` you should pass
    the `sha256` attribute instead of `md5`. You can pass either a
    hexadecimal or a base-32 encoding of the hash.

  - Nix can now perform builds in an automatically generated “chroot”.
    This prevents a builder from accessing stuff outside of the Nix
    store, and thus helps ensure purity. This is an experimental
    feature.

  - The new command `nix-store
            --optimise` reduces Nix store disk space usage by finding identical
    files in the store and hard-linking them to each other. It typically
    reduces the size of the store by something like 25-35%.

  - `~/.nix-defexpr` can now be a directory, in which case the Nix
    expressions in that directory are combined into an attribute set,
    with the file names used as the names of the attributes. The command
    `nix-env
            --import` (which set the `~/.nix-defexpr` symlink) is removed.

  - Derivations can specify the new special attribute
    `allowedReferences` to enforce that the references in the output of
    a derivation are a subset of a declared set of paths. For example,
    if `allowedReferences` is an empty list, then the output must not
    have any references. This is used in NixOS to check that generated
    files such as initial ramdisks for booting Linux don’t have any
    dependencies.

  - The new attribute `exportReferencesGraph` allows builders access to
    the references graph of their inputs. This is used in NixOS for
    tasks such as generating ISO-9660 images that contain a Nix store
    populated with the closure of certain paths.

  - Fixed-output derivations (like `fetchurl`) can define the attribute
    `impureEnvVars` to allow external environment variables to be passed
    to builders. This is used in Nixpkgs to support proxy configuration,
    among other things.

  - Several new built-in functions: `builtins.attrNames`,
    `builtins.filterSource`, `builtins.isAttrs`, `builtins.isFunction`,
    `builtins.listToAttrs`, `builtins.stringLength`, `builtins.sub`,
    `builtins.substring`, `throw`, `builtins.trace`,
    `builtins.readFile`.

---

### Doc Manual Source Release Notes Rl 0.12 (`doc/manual/source/release-notes/rl-0.12.md`)

# Release 0.12 (2008-11-20)

  - Nix no longer uses Berkeley DB to store Nix store metadata. The
    principal advantages of the new storage scheme are: it works
    properly over decent implementations of NFS (allowing Nix stores to
    be shared between multiple machines); no recovery is needed when a
    Nix process crashes; no write access is needed for read-only
    operations; no more running out of Berkeley DB locks on certain
    operations.
    
    You still need to compile Nix with Berkeley DB support if you want
    Nix to automatically convert your old Nix store to the new schema.
    If you don’t need this, you can build Nix with the `configure`
    option `--disable-old-db-compat`.
    
    After the automatic conversion to the new schema, you can delete the
    old Berkeley DB files:
    
        $ cd /nix/var/nix/db
        $ rm __db* log.* derivers references referrers reserved validpaths DB_CONFIG
    
    The new metadata is stored in the directories `/nix/var/nix/db/info`
    and `/nix/var/nix/db/referrer`. Though the metadata is stored in
    human-readable plain-text files, they are not intended to be
    human-editable, as Nix is rather strict about the format.
    
    The new storage schema may or may not require less disk space than
    the Berkeley DB environment, mostly depending on the cluster size of
    your file system. With 1 KiB clusters (which seems to be the `ext3`
    default nowadays) it usually takes up much less space.

  - There is a new substituter that copies paths directly from other
    (remote) Nix stores mounted somewhere in the filesystem. For
    instance, you can speed up an installation by mounting some remote
    Nix store that already has the packages in question via NFS or
    `sshfs`. The environment variable `NIX_OTHER_STORES` specifies the
    locations of the remote Nix directories, e.g. `/mnt/remote-fs/nix`.

  - New `nix-store` operations `--dump-db` and `--load-db` to dump and
    reload the Nix database.

  - The garbage collector has a number of new options to allow only some
    of the garbage to be deleted. The option `--max-freed N` tells the
    collector to stop after at least *N* bytes have been deleted. The
    option `--max-links
            N` tells it to stop after the link count on `/nix/store` has dropped
    below *N*. This is useful for very large Nix stores on filesystems
    with a 32000 subdirectories limit (like `ext3`). The option
    `--use-atime` causes store paths to be deleted in order of ascending
    last access time. This allows non-recently used stuff to be deleted.
    The option `--max-atime time` specifies an upper limit to the last
    accessed time of paths that may be deleted. For instance,
    
    ``` 
        $ nix-store --gc -v --max-atime $(date +%s -d "2 months ago")
    ```
    
    deletes everything that hasn’t been accessed in two months.

  - `nix-env` now uses optimistic profile locking when performing an
    operation like installing or upgrading, instead of setting an
    exclusive lock on the profile. This allows multiple `nix-env -i / -u
    / -e` operations on the same profile in parallel. If a `nix-env`
    operation sees at the end that the profile was changed in the
    meantime by another process, it will just restart. This is generally
    cheap because the build results are still in the Nix store.

  - The option `--dry-run` is now supported by `nix-store -r` and
    `nix-build`.

  - The information previously shown by `--dry-run` (i.e., which
    derivations will be built and which paths will be substituted) is
    now always shown by `nix-env`, `nix-store -r` and `nix-build`. The
    total download size of substitutable paths is now also shown. For
    instance, a build will show something like
    
        the following derivations will be built:
          /nix/store/129sbxnk5n466zg6r1qmq1xjv9zymyy7-activate-configuration.sh.drv
          /nix/store/7mzy971rdm8l566ch8hgxaf89x7lr7ik-upstart-jobs.drv
          ...
        the following paths will be downloaded/copied (30.02 MiB):
          /nix/store/4m8pvgy2dcjgppf5b4cj5l6wyshjhalj-samba-3.2.4
          /nix/store/spc1m987vlibchdx369qwa391s738s7l-libunwind-0.98.6
          ...

  - Language features:
    
      - @-patterns as in Haskell. For instance, in a function definition
        
            f = args @ {x, y, z}: ...;
        
        `args` refers to the argument as a whole, which is further
        pattern-matched against the attribute set pattern `{x, y, z}`.
    
      - “`...`” (ellipsis) patterns. An attribute set pattern can now
        say `...` at the end of the attribute name list to specify that
        the function takes *at least* the listed attributes, while
        ignoring additional attributes. For instance,
        
            {stdenv, fetchurl, fuse, ...}: ...
        
        defines a function that accepts any attribute set that includes
        at least the three listed attributes.
    
      - New primops: `builtins.parseDrvName` (split a package name
        string like `"nix-0.12pre12876"` into its name and version
        components, e.g. `"nix"` and `"0.12pre12876"`),
        `builtins.compareVersions` (compare two version strings using
        the same algorithm that `nix-env` uses), `builtins.length`
        (efficiently compute the length of a list), `builtins.mul`
        (integer multiplication), `builtins.div` (integer division).

  - `nix-prefetch-url` now supports `mirror://` URLs, provided that the
    environment variable `NIXPKGS_ALL` points at a Nixpkgs tree.

  - Removed the commands `nix-pack-closure` and `nix-unpack-closure`.
    You can do almost the same thing but much more efficiently by doing
    `nix-store --export
            $(nix-store -qR paths) > closure` and `nix-store --import <
            closure`.

  - Lots of bug fixes, including a big performance bug in the handling
    of `with`-expressions.

---

### Doc Manual Source Release Notes Rl 0.13 (`doc/manual/source/release-notes/rl-0.13.md`)

# Release 0.13 (2009-11-05)

This is primarily a bug fix release. It has some new features:

  - Syntactic sugar for writing nested attribute sets. Instead of
    
        {
          foo = {
            bar = 123;
            xyzzy = true;
          };
          a = { b = { c = "d"; }; };
        }
    
    you can write
    
        {
          foo.bar = 123;
          foo.xyzzy = true;
          a.b.c = "d";
        }
    
    This is useful, for instance, in NixOS configuration files.

  - Support for Nix channels generated by Hydra, the Nix-based
    continuous build system. (Hydra generates NAR archives on the fly,
    so the size and hash of these archives isn’t known in advance.)

  - Support `i686-linux` builds directly on `x86_64-linux` Nix
    installations. This is implemented using the `personality()`
    syscall, which causes `uname` to return `i686` in child processes.

  - Various improvements to the `chroot` support. Building in a `chroot`
    works quite well now.

  - Nix no longer blocks if it tries to build a path and another process
    is already building the same path. Instead it tries to build another
    buildable path first. This improves parallelism.

  - Support for large (\> 4 GiB) files in NAR archives.

  - Various (performance) improvements to the remote build mechanism.

  - New primops: `builtins.addErrorContext` (to add a string to stack
    traces — useful for debugging), `builtins.isBool`,
    `builtins.isString`, `builtins.isInt`, `builtins.intersectAttrs`.

  - OpenSolaris support (Sander van der Burg).

  - Stack traces are no longer displayed unless the `--show-trace`
    option is used.

  - The scoping rules for `inherit
                    (e) ...` in recursive attribute sets have changed. The expression
    *e* can now refer to the attributes defined in the containing set.

---

### Doc Manual Source Release Notes Rl 0.14 (`doc/manual/source/release-notes/rl-0.14.md`)

# Release 0.14 (2010-02-04)

This release has the following improvements:

  - The garbage collector now starts deleting garbage much faster than
    before. It no longer determines liveness of all paths in the store,
    but does so on demand.

  - Added a new operation, `nix-store --query
                    --roots`, that shows the garbage collector roots that directly or
    indirectly point to the given store paths.

  - Removed support for converting Berkeley DB-based Nix databases to
    the new schema.

  - Removed the `--use-atime` and `--max-atime` garbage collector
    options. They were not very useful in practice.

  - On Windows, Nix now requires Cygwin 1.7.x.

  - A few bug fixes.

---

### Doc Manual Source Release Notes Rl 0.15 (`doc/manual/source/release-notes/rl-0.15.md`)

# Release 0.15 (2010-03-17)

This is a bug-fix release. Among other things, it fixes building on Mac
OS X (Snow Leopard), and improves the contents of `/etc/passwd` and
`/etc/group` in `chroot` builds.

---

### Doc Manual Source Release Notes Rl 0.16 (`doc/manual/source/release-notes/rl-0.16.md`)

# Release 0.16 (2010-08-17)

This release has the following improvements:

  - The Nix expression evaluator is now much faster in most cases:
    typically, [3 to 8 times compared to the old
    implementation](http://www.mail-archive.com/[email protected]/msg04113.html).
    It also uses less memory. It no longer depends on the ATerm library.

  - Support for configurable parallelism inside builders. Build scripts
    have always had the ability to perform multiple build actions in
    parallel (for instance, by running `make -j
                            2`), but this was not desirable because the number of actions to be
    performed in parallel was not configurable. Nix now has an option
    `--cores
                            N` as well as a configuration setting `build-cores =
                            N` that causes the environment variable `NIX_BUILD_CORES` to be set
    to *N* when the builder is invoked. The builder can use this at its
    discretion to perform a parallel build, e.g., by calling `make -j
                            N`. In Nixpkgs, this can be enabled on a per-package basis by
    setting the derivation attribute `enableParallelBuilding` to `true`.

  - `nix-store -q` now supports XML output through the `--xml` flag.

  - Several bug fixes.

---

### Doc Manual Source Release Notes Rl 0.5 (`doc/manual/source/release-notes/rl-0.5.md`)

# Release 0.5 and earlier

Please refer to the Subversion commit log messages.

---

### Doc Manual Source Release Notes Rl 0.6 (`doc/manual/source/release-notes/rl-0.6.md`)

# Release 0.6 (2004-11-14)

  - Rewrite of the normalisation engine.
    
      - Multiple builds can now be performed in parallel (option `-j`).
    
      - Distributed builds. Nix can now call a shell script to forward
        builds to Nix installations on remote machines, which may or may
        not be of the same platform type.
    
      - Option `--fallback` allows recovery from broken substitutes.
    
      - Option `--keep-going` causes building of other (unaffected)
        derivations to continue if one failed.

  - Improvements to the garbage collector (i.e., it should actually work
    now).

  - Setuid Nix installations allow a Nix store to be shared among
    multiple users.

  - Substitute registration is much faster now.

  - A utility `nix-build` to build a Nix expression and create a symlink
    to the result int the current directory; useful for testing Nix
    derivations.

  - Manual updates.

  - `nix-env` changes:
    
      - Derivations for other platforms are filtered out (which can be
        overridden using `--system-filter`).
    
      - `--install` by default now uninstall previous derivations with
        the same name.
    
      - `--upgrade` allows upgrading to a specific version.
    
      - New operation `--delete-generations` to remove profile
        generations (necessary for effective garbage collection).
    
      - Nicer output (sorted, columnised).

  - More sensible verbosity levels all around (builder output is now
    shown always, unless `-Q` is given).

  - Nix expression language changes:
    
      - New language construct: `with
                                                        E1;
                                                        E2` brings all attributes defined in the attribute set *E1* in
        scope in *E2*.
    
      - Added a `map` function.
    
      - Various new operators (e.g., string concatenation).

  - Expression evaluation is much faster.

  - An Emacs mode for editing Nix expressions (with syntax highlighting
    and indentation) has been added.

  - Many bug fixes.

---

### Doc Manual Source Release Notes Rl 0.7 (`doc/manual/source/release-notes/rl-0.7.md`)

# Release 0.7 (2005-01-12)

  - Binary patching. When upgrading components using pre-built binaries
    (through nix-pull / nix-channel), Nix can automatically download and
    apply binary patches to already installed components instead of full
    downloads. Patching is “smart”: if there is a *sequence* of patches
    to an installed component, Nix will use it. Patches are currently
    generated automatically between Nixpkgs (pre-)releases.

  - Simplifications to the substitute mechanism.

  - Nix-pull now stores downloaded manifests in
    `/nix/var/nix/manifests`.

  - Metadata on files in the Nix store is canonicalised after builds:
    the last-modified timestamp is set to 0 (00:00:00 1/1/1970), the
    mode is set to 0444 or 0555 (readable and possibly executable by
    all; setuid/setgid bits are dropped), and the group is set to the
    default. This ensures that the result of a build and an installation
    through a substitute is the same; and that timestamp dependencies
    are revealed.

---

### Doc Manual Source Release Notes Rl 0.8.1 (`doc/manual/source/release-notes/rl-0.8.1.md`)

# Release 0.8.1 (2005-04-13)

This is a bug fix release.

  - Patch downloading was broken.

  - The garbage collector would not delete paths that had references
    from invalid (but substitutable) paths.

---

### Doc Manual Source Release Notes Rl 0.8 (`doc/manual/source/release-notes/rl-0.8.md`)

# Release 0.8 (2005-04-11)

NOTE: the hashing scheme in Nix 0.8 changed (as detailed below). As a
result, `nix-pull` manifests and channels built for Nix 0.7 and below
will not work anymore. However, the Nix expression language has not
changed, so you can still build from source. Also, existing user
environments continue to work. Nix 0.8 will automatically upgrade the
database schema of previous installations when it is first run.

If you get the error message

    you have an old-style manifest `/nix/var/nix/manifests/[...]'; please
    delete it

you should delete previously downloaded manifests:

    $ rm /nix/var/nix/manifests/*

If `nix-channel` gives the error message

    manifest `http://catamaran.labs.cs.uu.nl/dist/nix/channels/[channel]/MANIFEST'
    is too old (i.e., for Nix <= 0.7)

then you should unsubscribe from the offending channel (`nix-channel
--remove
URL`; leave out `/MANIFEST`), and subscribe to the same URL, with
`channels` replaced by `channels-v3` (e.g.,
<http://catamaran.labs.cs.uu.nl/dist/nix/channels-v3/nixpkgs-unstable>).

Nix 0.8 has the following improvements:

  - The cryptographic hashes used in store paths are now 160 bits long,
    but encoded in base-32 so that they are still only 32 characters
    long (e.g.,
    `/nix/store/csw87wag8bqlqk7ipllbwypb14xainap-atk-1.9.0`). (This is
    actually a 160 bit truncation of a SHA-256 hash.)

  - Big cleanups and simplifications of the basic store semantics. The
    notion of “closure store expressions” is gone (and so is the notion
    of “successors”); the file system references of a store path are now
    just stored in the database.

    For instance, given any store path, you can query its closure:

        $ nix-store -qR $(which firefox)
        ... lots of paths ...

    Also, Nix now remembers for each store path the derivation that
    built it (the “deriver”):

        $ nix-store -qR $(which firefox)
        /nix/store/4b0jx7vq80l9aqcnkszxhymsf1ffa5jd-firefox-1.0.1.drv

    So to see the build-time dependencies, you can do

        $ nix-store -qR $(nix-store -qd $(which firefox))

    or, in a nicer format:

        $ nix-store -q --tree $(nix-store -qd $(which firefox))

    File system references are also stored in reverse. For instance, you
    can query all paths that directly or indirectly use a certain Glibc:

        $ nix-store -q --referrers-closure \
            /nix/store/1a6mdrjz4wn7b9sfmcw5ggbk1mi281mh-glibc-2.3.4

  - The concept of fixed-output derivations has been formalised.
    Previously, functions such as `fetchurl` in Nixpkgs used a hack
    (namely, explicitly specifying a store path hash) to prevent changes
    to, say, the URL of the file from propagating upwards through the
    dependency graph, causing rebuilds of everything. This can now be
    done cleanly by specifying the `outputHash` and `outputHashAlgo`
    attributes. Nix itself checks that the content of the output has the
    specified hash. (This is important for maintaining certain
    invariants necessary for future work on secure shared stores.)

  - One-click installation :-) It is now possible to install any
    top-level component in Nixpkgs directly, through the web — see,
    e.g., <http://catamaran.labs.cs.uu.nl/dist/nixpkgs-0.8/>. All you
    have to do is associate `/nix/bin/nix-install-package` with the MIME
    type `application/nix-package` (or the extension `.nixpkg`), and
    clicking on a package link will cause it to be installed, with all
    appropriate dependencies. If you just want to install some specific
    application, this is easier than subscribing to a channel.

  - `nix-store -r
            PATHS` now builds all the derivations PATHS in parallel. Previously
    it did them sequentially (though exploiting possible parallelism
    between subderivations). This is nice for build farms.

  - `nix-channel` has new operations `--list` and `--remove`.

  - New ways of installing components into user environments:

      - Copy from another user environment:

            $ nix-env -i --from-profile .../other-profile firefox

      - Install a store derivation directly (bypassing the Nix
        expression language entirely):

            $ nix-env -i /nix/store/z58v41v21xd3...-aterm-2.3.1.drv

        (This is used to implement `nix-install-package`, which is
        therefore immune to evolution in the Nix expression language.)

      - Install an already built store path directly:

            $ nix-env -i /nix/store/hsyj5pbn0d9i...-aterm-2.3.1

      - Install the result of a Nix expression specified as a
        command-line argument:

            $ nix-env -f .../i686-linux.nix -i -E 'x: x.firefoxWrapper'

        The difference with the normal installation mode is that `-E`
        does not use the `name` attributes of derivations. Therefore,
        this can be used to disambiguate multiple derivations with the
        same name.

  - A hash of the contents of a store path is now stored in the database
    after a successful build. This allows you to check whether store
    paths have been tampered with: `nix-store
            --verify --check-contents`.

  - Implemented a concurrent garbage collector. It is now always safe to
    run the garbage collector, even if other Nix operations are
    happening simultaneously.

    However, there can still be GC races if you use `nix-instantiate`
    and `nix-store
                    --realise` directly to build things. To prevent races, use the
    `--add-root` flag of those commands.

  - The garbage collector now finally deletes paths in the right order
    (i.e., topologically sorted under the “references” relation), thus
    making it safe to interrupt the collector without risking a store
    that violates the closure invariant.

  - Likewise, the substitute mechanism now downloads files in the right
    order, thus preserving the closure invariant at all times.

  - The result of `nix-build` is now registered as a root of the garbage
    collector. If the `./result` link is deleted, the GC root disappears
    automatically.

  - The behaviour of the garbage collector can be changed globally by
    setting options in `/nix/etc/nix/nix.conf`.

      - `gc-keep-derivations` specifies whether deriver links should be
        followed when searching for live paths.

      - `gc-keep-outputs` specifies whether outputs of derivations
        should be followed when searching for live paths.

      - `env-keep-derivations` specifies whether user environments
        should store the paths of derivations when they are added (thus
        keeping the derivations alive).

  - New `nix-env` query flags `--drv-path` and `--out-path`.

  - `fetchurl` allows SHA-1 and SHA-256 in addition to MD5. Just specify
    the attribute `sha1` or `sha256` instead of `md5`.

  - Manual updates.

---

### Doc Manual Source Release Notes Rl 0.9.1 (`doc/manual/source/release-notes/rl-0.9.1.md`)

# Release 0.9.1 (2005-09-20)

This bug fix release addresses a problem with the ATerm library when the
`--with-aterm` flag in `configure` was *not* used.

---

### Doc Manual Source Release Notes Rl 0.9.2 (`doc/manual/source/release-notes/rl-0.9.2.md`)

# Release 0.9.2 (2005-09-21)

This bug fix release fixes two problems on Mac OS X:

  - If Nix was linked against statically linked versions of the ATerm or
    Berkeley DB library, there would be dynamic link errors at runtime.

  - `nix-pull` and `nix-push` intermittently failed due to race
    conditions involving pipes and child processes with error messages
    such as `open2: open(GLOB(0x180b2e4), >&=9) failed: Bad
            file descriptor at /nix/bin/nix-pull line 77` (issue `NIX-14`).

---

### Doc Manual Source Release Notes Rl 0.9 (`doc/manual/source/release-notes/rl-0.9.md`)

# Release 0.9 (2005-09-16)

NOTE: this version of Nix uses Berkeley DB 4.3 instead of 4.2. The
database is upgraded automatically, but you should be careful not to use
old versions of Nix that still use Berkeley DB 4.2. In particular, if
you use a Nix installed through Nix, you should run

    $ nix-store --clear-substitutes

first.

  - Unpacking of patch sequences is much faster now since we no longer
    do redundant unpacking and repacking of intermediate paths.

  - Nix now uses Berkeley DB 4.3.

  - The `derivation` primitive is lazier. Attributes of dependent
    derivations can mutually refer to each other (as long as there are
    no data dependencies on the `outPath` and `drvPath` attributes
    computed by `derivation`).
    
    For example, the expression `derivation
            attrs` now evaluates to (essentially)
    
        attrs // {
          type = "derivation";
          outPath = derivation! attrs;
          drvPath = derivation! attrs;
        }
    
    where `derivation!` is a primop that does the actual derivation
    instantiation (i.e., it does what `derivation` used to do). The
    advantage is that it allows commands such as `nix-env -qa` and
    `nix-env -i` to be much faster since they no longer need to
    instantiate all derivations, just the `name` attribute.
    
    Also, it allows derivations to cyclically reference each other, for
    example,
    
        webServer = derivation {
          ...
          hostName = "svn.cs.uu.nl";
          services = [svnService];
        };
         
        svnService = derivation {
          ...
          hostName = webServer.hostName;
        };
    
    Previously, this would yield a black hole (infinite recursion).

  - `nix-build` now defaults to using `./default.nix` if no Nix
    expression is specified.

  - `nix-instantiate`, when applied to a Nix expression that evaluates
    to a function, will call the function automatically if all its
    arguments have defaults.

  - Nix now uses libtool to build dynamic libraries. This reduces the
    size of executables.

  - A new list concatenation operator `++`. For example, `[1 2 3] ++
    [4 5
            6]` evaluates to `[1 2 3 4 5
            6]`.

  - Some currently undocumented primops to support low-level build
    management using Nix (i.e., using Nix as a Make replacement). See
    the commit messages for `r3578` and `r3580`.

  - Various bug fixes and performance improvements.

---

### Doc Manual Source Release Notes Rl 1.0 (`doc/manual/source/release-notes/rl-1.0.md`)

# Release 1.0 (2012-05-11)

There have been numerous improvements and bug fixes since the previous
release. Here are the most significant:

  - Nix can now optionally use the Boehm garbage collector. This
    significantly reduces the Nix evaluator’s memory footprint,
    especially when evaluating large NixOS system configurations. It can
    be enabled using the `--enable-gc` configure option.

  - Nix now uses SQLite for its database. This is faster and more
    flexible than the old *ad hoc* format. SQLite is also used to cache
    the manifests in `/nix/var/nix/manifests`, resulting in a
    significant speedup.

  - Nix now has an search path for expressions. The search path is set
    using the environment variable `NIX_PATH` and the `-I` command line
    option. In Nix expressions, paths between angle brackets are used to
    specify files that must be looked up in the search path. For
    instance, the expression `<nixpkgs/default.nix>` looks for a file
    `nixpkgs/default.nix` relative to every element in the search path.

  - The new command `nix-build --run-env` builds all dependencies of a
    derivation, then starts a shell in an environment containing all
    variables from the derivation. This is useful for reproducing the
    environment of a derivation for development.

  - The new command `nix-store --verify-path` verifies that the contents
    of a store path have not changed.

  - The new command `nix-store --print-env` prints out the environment
    of a derivation in a format that can be evaluated by a shell.

  - Attribute names can now be arbitrary strings. For instance, you can
    write `{ "foo-1.2" = …; "bla bla" = …; }."bla
                    bla"`.

  - Attribute selection can now provide a default value using the `or`
    operator. For instance, the expression `x.y.z or e` evaluates to the
    attribute `x.y.z` if it exists, and `e` otherwise.

  - The right-hand side of the `?` operator can now be an attribute
    path, e.g., `attrs ?
                    a.b.c`.

  - On Linux, Nix will now make files in the Nix store immutable on
    filesystems that support it. This prevents accidental modification
    of files in the store by the root user.

  - Nix has preliminary support for derivations with multiple outputs.
    This is useful because it allows parts of a package to be deployed
    and garbage-collected separately. For instance, development parts of
    a package such as header files or static libraries would typically
    not be part of the closure of an application, resulting in reduced
    disk usage and installation time.

  - The Nix store garbage collector is faster and holds the global lock
    for a shorter amount of time.

  - The option `--timeout` (corresponding to the configuration setting
    `build-timeout`) allows you to set an absolute timeout on builds —
    if a build runs for more than the given number of seconds, it is
    terminated. This is useful for recovering automatically from builds
    that are stuck in an infinite loop but keep producing output, and
    for which `--max-silent-time` is ineffective.

  - Nix development has moved to GitHub
    (<https://github.com/NixOS/nix>).

---

### Doc Manual Source Release Notes Rl 1.1 (`doc/manual/source/release-notes/rl-1.1.md`)

# Release 1.1 (2012-07-18)

This release has the following improvements:

  - On Linux, when doing a chroot build, Nix now uses various namespace
    features provided by the Linux kernel to improve build isolation.
    Namely:
    
      - The private network namespace ensures that builders cannot talk
        to the outside world (or vice versa): each build only sees a
        private loopback interface. This also means that two concurrent
        builds can listen on the same port (e.g. as part of a test)
        without conflicting with each other.
    
      - The PID namespace causes each build to start as PID 1. Processes
        outside of the chroot are not visible to those on the inside. On
        the other hand, processes inside the chroot *are* visible from
        the outside (though with different PIDs).
    
      - The IPC namespace prevents the builder from communicating with
        outside processes using SysV IPC mechanisms (shared memory,
        message queues, semaphores). It also ensures that all IPC
        objects are destroyed when the builder exits.
    
      - The UTS namespace ensures that builders see a hostname of
        `localhost` rather than the actual hostname.
    
      - The private mount namespace was already used by Nix to ensure
        that the bind-mounts used to set up the chroot are cleaned up
        automatically.

  - Build logs are now compressed using `bzip2`. The command `nix-store
                    -l` decompresses them on the fly. This can be disabled by setting
    the option `build-compress-log` to `false`.

  - The creation of build logs in `/nix/var/log/nix/drvs` can be
    disabled by setting the new option `build-keep-log` to `false`. This
    is useful, for instance, for Hydra build machines.

  - Nix now reserves some space in `/nix/var/nix/db/reserved` to ensure
    that the garbage collector can run successfully if the disk is full.
    This is necessary because SQLite transactions fail if the disk is
    full.

  - Added a basic `fetchurl` function. This is not intended to replace
    the `fetchurl` in Nixpkgs, but is useful for bootstrapping; e.g.,