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.
- The Nix, Nixpkgs, NixOS Community on nixos.org
- Official documentation on nix.dev
- Nixpkgs is the largest, most up-to-date free software repository in the world
- NixOS is a Linux distribution that can be configured fully declaratively
- Discourse
- Matrix: #users:nixos.org for user support and #nix-dev:nixos.org for development
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.
- Triage issues and pull requests from the No Status column (30 min)
- 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.
- Code review on pull requests from In review.
- 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:
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:
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| MergedOverview (`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
Eelco Dolstra
GPG Fingerprint:B541 D553 0127 0E0B CF15 CA5D 8170 B472 6D71 98DESergei Zimmerman
GPG Fingerprint:158A 6F53 0EA2 02E5 F651 6113 14FA EA63 448E 1DF9
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:
- Embedding the evaluator
- 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:
#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:
$ gcc main.c $(pkg-config nix-expr-c --libs --cflags) -o main
$ ./main
Nix version: 2.17Writing 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:
#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:
$ 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
2Overview (`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
consoleerror: the user '_nixbld1' in the group 'nixbld' does not existwhen running Nix commands, refer to GitHub issue NixOS/nix#10892 for instructions to fix your installation without reinstalling.
$ curl -L https://nixos.org/nix/install | sh -s -- --daemonSingle-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.
$ curl -L https://nixos.org/nix/install | sh -s -- --no-daemonDistributions
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:- File system path primitives, for accessing source files
- Indented strings and string interpolation, for creating file contents
- Strings with contexts, for transparently linking files
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 |
| ``` | |
| '' |
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-infofile at the root with remote-side configuration. - For each store object:
- A
.narinfofile 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.
- A
- For every entry in the build trace, a JSON file at
build-trace-v2/<drvBaseName>/<outputName>.doi:
The following store types use the binary cache format:
- HTTP Binary Cache Store — served over HTTP(S)
- Local Binary Cache Store — stored on the file system
- S3 Binary Cache Store — stored in an AWS S3 bucket
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.
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 numbernpad(s)= the byte sequences, 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).
{{#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:
A name
An inputs specification, a set of deriving paths
An outputs specification, specifying which outputs should be produced, and various metadata about them.
The "system" type (e.g.
x86_64-linux) where the executable is to run.The process creation fields: to spawn the arbitrary process which will perform the build step.
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:
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 bynix-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
cpioarchive 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 itssystem-featuresfor 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 thealways-allow-substitutesconfiguration 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-envexperimental feature is enabled,
these environment variables can also be controlled through theimpure-envconfiguration 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:
The legacy "ATerm" format
The experimental, currently under development and changing JSON format
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^outThis 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:
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:
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, anddev
The derivation's path will be:
/nix/store/<hash>-hello.drv.The store path of
outwill be:/nix/store/<hash>-hello.The store path of
devwill 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
devoutput" means the store object referred to by the store path/nix/store/<hash>-hello-dev.
It is unusual to call this the "hello-devoutput", even thoughhello-devis 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:
whether the output is content-addressed or input-addressed
if the content is content-addressed, how is it content addressed
if the content is content-addressed, what is its content address (and thus what is its store path)
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 nameoutis special, according to the rules described above.
Having only one output and calling its specificationoutmeans 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-derivationsexperimental 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. systemdDelegate=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
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 encounteredDoc 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:
- C API documentation for a recent build of master
- Matrix Room Nix Bindings for discussion and questions.
- Stabilisation Milestone
- Other C API PRs and issues
- Contributing C API Documentation, including how to build it locally.
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.
binary cache{#gloss-binary-cache}
A binary cache is a Nix store which uses a different format: its
metadata and signatures are kept in.narinfofiles 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 commandnix-store --query --requisitesprints out
closures of store paths.As an example, if the store object at path
Pcontains a reference
to a store object at pathQ, thenQis in the closure ofP. Further, ifQ
referencesRthenRis also in the closure ofP.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:
- Content-Addressing File System Objects
- Content-Addressing Store Objects
- content-addressing derivation
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 totrue.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
derivationprimitive 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
--deriveroption tonix-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 theexperimental-featuressetting.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
outputHashattribute, and where thebuilderexecutable 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}
[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
nixcommands (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 usingnix-store --dump
andnix-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
.nixfile 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}
- 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. - A running Nix process, such as the
nixcommand.
- An installation of Nix, which includes the presence of a store, and the Nix package manager which operates on that store.
output{#gloss-output}
A store object produced by a store derivation.
See theoutputsargument to thederivationfunction 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
Qis reachable from another store pathPifQ
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:
- Fetching a pre-built store object from a substituter
- Building the corresponding store derivation
- Delegating to a remote machine and retrieving the outputs
See
nix-store --realisefor a detailed description of the algorithm.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.1See 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
substitutersconfiguration 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 bynix-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:
- The store path leads to an existing store object in that store.
- The store path is listed in the Nix database as being valid.
- All paths in the store path's closure are valid.
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
/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:
$ nix-env --upgrade --attr nixpkgs.some-package
$ nix-env --rollbackGarbage collection
When you uninstall a package like this…
$ nix-env --uninstall firefoxthe 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:
$ nix-collect-garbageThis 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
$ nix-env --install --attr nixpkgs.firefoxcould 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:
$ nix-shell '<nixpkgs>' --attr panYou’re then dropped into a shell where you can edit, build and test
the package:
[nix-shell]$ unpackPhase
[nix-shell]$ cd pan-*
[nix-shell]$ configurePhase
[nix-shell]$ buildPhase
[nix-shell]$ ./pan/gui/panPortability
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.
Install Nix:
console$ curl -L https://nixos.org/nix/install | shThe install script will use
sudo, so make sure you have sufficient rights.For other installation methods, see the detailed installation instructions.
Run software without installing it permanently:
console$ nix-shell --packages cowsay lolcatThis 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! | lolcatExiting the shell will make the programs disappear again:
console[nix-shell:~]$ exit $ lolcat lolcat: command not foundSearch for more packages on search.nixos.org to try them out.
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 tomake -j.
The cores setting determines the value ofNIX_BUILD_CORES. NIX_BUILD_CORES is equal to cores, unlesscores 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:
let
inherit (import <nixpkgs> {}) runCommand;
in {
stable = runCommand "stable" {} ''
touch $out
'';
unstable = runCommand "unstable" {} ''
echo $RANDOM > $out
'';
}Additionally, nix.conf contains:
diff-hook = /etc/nix/my-diff-hook
run-diff-hook = truewhere /etc/nix/my-diff-hook is an executable file containing:
#!/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:
$ 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-stableIf the build is not deterministic, Nix will exit with a status code of
1:
$ 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' differsIn the Nix daemon's log, we will now see:
For derivation /nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv:
1c1
< 8108
---
> 30204Using --check with --keep-failed will cause Nix to keep the second
build's output in a special, .check path:
$ 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
thediff-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:
error: some outputs of '/nix/store/hzi1h60z2qf0nb85iwnpvrai3j2w7rr6-unstable.drv'
are not valid, so checking is not possibleRun 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 aaarch64-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-userssetting innix.conf
Testing
To test connecting to a remote Nix instance (in this case mac), run:
nix store info --store ssh://username@macTo specify an SSH identity file as part of the remote store URI add a
query parameter, e.g.
nix store info --store ssh://username@mac?ssh-key=/home/alice/my-keySince builds should be non-interactive, the key should not have a
passphrase. Alternatively, you can load identities ahead of time intossh-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
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:
unameLinuxnix build --impure \
--expr '(with import <nixpkgs> { system = "aarch64-darwin"; }; runCommand "foo" {} "uname > $out")' \
--builders 'ssh://mac aarch64-darwin'[1/0/1 built, 0.0 MiB DL] building foo on ssh://maccat ./resultDarwinIt is possible to specify multiple build machines separated by a semicolon or a newline, e.g.
--builders 'ssh://mac aarch64-darwin ; ssh://beastie x86_64-freebsd'Remote build machines can also be configured in nix.conf, e.g.
builders = ssh://mac aarch64-darwin ; ssh://beastie x86_64-freebsdAfter 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,
builders = @/etc/nix/machinescauses 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 theeval-profiler
setting:
$ nix-instantiate "<nixpkgs>" -A hello --eval-profiler flamegraphStack sampling frequency and the output file path can be configured witheval-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:
$ flamegraph.pl nix.profile > flamegraph.svgThe 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:
/nix/store/2q71fdvr4h33g9832hiriwnf20fn630l-source/pkgs/top-level/default.nix:167:5:primop importHere 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.
# 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:
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:
secret-key-files = /etc/nix/key.privateWe will restart the Nix daemon in a later step.
Implementing the build hook
Write the following script to /etc/nix/upload-to-cache.sh:
#!/bin/sh
set -eu
set -f # disable globbing
export IFS=' '
echo "Uploading paths" $OUT_PATHS
exec nix copy --to "s3://example-nix-cache" $OUT_PATHSNote
The
$OUT_PATHSvariable 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 tonix store sign. Nix guarantees the paths will not contain any spaces,
however a store path might contain glob characters. Theset -f
disables globbing in the shell.
If you want to upload the.drvfile too, the$DRV_PATHvariable
is also defined for the script and works just like$OUT_PATHS.
Then make sure the hook program is executable by the root user:
# chmod +x /etc/nix/upload-to-cache.shUpdating Nix Configuration
Edit /etc/nix/nix.conf to run our hook, by adding the following
configuration snippet at the end:
post-build-hook = /etc/nix/upload-to-cache.shThen, restart the nix-daemon.
Testing
Build any derivation, for example:
$ 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-exampleThen delete the path from the store, and try substituting it from the
binary cache:
$ rm ./result
$ nix-store --delete /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-exampleNow, copy the path back from the cache:
$ 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-exampleConclusion
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):
/* 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:
/* 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.
The system-wide configuration file
nix.confin the configuration directory.The configuration directory defaults to
${sysconfdir}/nix(i.e./etc/nixon most Unix systems) or%PROGRAMDATA%\nix\confon Windows, and can be overridden withNIX_CONF_DIR.Values loaded in this file are not forwarded to the Nix daemon.
The client assumes that the daemon has already loaded them.If
NIX_USER_CONF_FILESis 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.confin:- The user configuration directory
- On Unix additionally,
nix/nix.confunder each directory inXDG_CONFIG_DIRS
If
NIX_CONFIGis 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:
keep-outputs = true # Nice for developers
keep-derivations = true # IdemOther 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,
substituters = a b
extra-substituters = c ddefines 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 theno-prefix (e.g.--keep-failedand--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.
-
Overrides the system configuration directory.
-
Overrides the user configuration file locations.
-
Provides configuration settings inline.
Store setting environment variables
-
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/storeresolving to different locations) could yield
different results. This is generally not a problem, except when
builds are deployed to machines where/nix/storeresolves
differently. If you are sure that you’re not going to do that, you
can setNIX_IGNORE_SYMLINK_STOREto1.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 usingbindmount points, e.g.,console$ mkdir /nix $ mount -o bind /mnt/otherdisk/nix /nixConsult the mount 8 manual page for details.
-
Overrides the location of the Nix store.
On Unix, the default is/nix/store, set at compile time by thelibstore:store-dirbuild 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
storesetting linking back to this as its default. -
Overrides the location of the Nix log directory.
On Unix, the default is/nix/var/log/nix, set at compile time by thelog-dirbuild 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.
-
Overrides the location of the Nix state directory.
On Unix, the default is${localstatedir}/nix, wherelocalstatediris 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.
-
Overrides the path to the Unix domain socket used to communicate with the Nix daemon.
Defaults todaemon-socket/socketwithin the state directory (seeNIX_STATE_DIR).See the Local Daemon Store documentation for details on how the socket path is resolved.
-
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. -
Overrides the
storesetting.
Nix language evaluator settings
-
If set to
1, Nix will print some evaluation statistics, such as
the number of values allocated. -
If set to
1, Nix will print how often functions were called during
Nix expression evaluation. This is useful for profiling your Nix
expressions. -
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. -
A colon-separated list of search path entries used to resolve lookup paths.
This environment variable overrides the value of the
nix-pathconfiguration setting.It can be extended using the
-Ioption.Example
bash$ export NIX_PATH=/home/eelco/Dev:nixos-config=/etc/nixosIf
NIX_PATHis 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:
$NIX_CONFIG_HOME, if it is defined- Otherwise, the platform default (e.g.
$XDG_CONFIG_HOME/nixon Unix)
Likewise for the state and cache directories.
Miscellaneous environment variables
-
Indicator that tells if the current environment was set up by
nix-shell. It can have the valuespureorimpure.
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 afterXDG_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 aroundnix-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 theresultsymlink is deleted or renamed. So don’t rename the symlink.
Options
All options not listed here are passed tonix-store --realise,
except for --arg and --attr / -A which are passed to nix-instantiate.
-
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 bynix-store --gc. -
Show what store paths would be built or downloaded.
--out-link/-ooutlinkChange the name of the symlink to the output path created from
resultto outlink.
{{#include ./status-build-failure.md}}
{{#include ./opt-common.md}}
{{#include ./env-common.md}}
Examples
$ 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-configIf a derivation has multiple outputs, nix-build will build the default
(first) output. You can also build all outputs:
$ nix-build '<nixpkgs>' --attr openssl.allThis 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 symlinksresult, result-bin and result-man. It’s also possible to build a
specific output:
$ nix-build '<nixpkgs>' --attr openssl.manThis will create a symlink result-man.
Build a Nix expression given on the command line:
$ nix-build --expr 'with import <nixpkgs> { }; runCommand "foo" { } "echo bar > $out"'
$ cat ./result
barBuild the GNU Hello package from the latest revision of the master
branch of Nixpkgs:
$ nix-build https://github.com/NixOS/nixpkgs/archive/master.tar.gz --attr helloDoc 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:
- The official channels listed at https://channels.nixos.org
- The user-specific list of subscribed channels
- The downloaded channel contents
- The Nix expression search path, set with the
-Ioption or theNIX_PATHenvironment variable
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:
fetchurl,fetchTarball, orfetchGitin Nix expressions- the
-Ioption in command line invocations
This command has the following operations:
--addurl [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-stableor-unstableremoved.Note
--adddoes not automatically perform an update.
Use--updateexplicitly.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 adefault.nixfile that serves as the channel’s entry point.--removenameRemove the channel name from the list of subscribed channels.
--listPrint 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-ttlor thetarball-ttlconfiguration option to change the validity period of cached downloads.--list-generationsPrints a list of all the current existing generations for the
channel profile.Works the same way as
textnix-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:
$ 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
helloRevert channel updates using --rollback:
$ 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:
$ nix-channel --remove nixpkgs
$ nix-channel --listDoc 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 runningnix-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:
The default profile locations as specified in the profiles section of the manual.
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/profilesand$NIX_STATE_DIR/profiles/per-user.With the exception of
$NIX_STATE_DIR/profiles/per-user/rootand$NIX_STATE_DIR/profiles/default, these directories are no longer used by other commands.nix-collect-garbagelooks 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/-dDelete all old generations of profiles.
This is the equivalent of invoking
nix-env --delete-generations oldon each found profile.--delete-older-thanperiodDelete 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 as30d, which would mean 30 days.This is the equivalent of invoking
nix-env --delete-generationson each found profile.
See the documentation of that command for additional information about the period argument.--max-freedbytesKeep deleting paths until at least bytes bytes have been deleted,
then stop. The argument bytes can be followed by the
multiplicative suffixK,M,GorT, 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
$ nix-collect-garbage -dDoc 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
--storeoption, 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
--toCopy 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.--fromCopy the closure of paths from the Nix store on the remote machine to the local machine's specified Nix store.
--gzipEnable compression of the SSH connection.
--include-outputsAlso copy the outputs of store derivations included in the closure.
--use-substitutes/-sAttempt 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 andcache.nixos.org(the default binary cache server) is fast.
{{#include ./opt-common.md}}
Environment variables
NIX_SSHOPTSAdditional options to be passed to
sshon 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:
--install--upgrade--uninstall--set--set-flag--query--switch-profile--list-generations--delete-generations--switch-generation--rollback
These pages can be viewed offline:
man nix-env-<operation>.Example:
man nix-env-installnix-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-envparses the symbolic derivation nameapache-httpd-2.0.48as:json{ "name": "apache-httpd", "version": "2.0.48" }
Example
nix-envparses the symbolic derivation namefirefox.*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:
firefoxMatches the package name
firefoxand any version.
firefox-32.0Matches the package name
firefoxand version32.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
firefoxorchromium.
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 asnix-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
--flatPrint 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 commandsmd5sumandsha1sum.--base16Print the hash in a hexadecimal representation (default).
--base32Print the hash in Nix32 representation rather than hexadecimal.
This representation is more compact and can be used in Nix
expressions (such as in calls tofetchurl).--base64Similar to
--base32, but print the hash in a Base64 representation,
which is more compact than the Nix32 one.--sriPrint 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.--truncateTruncate hashes longer than 160 bits (such as SHA-256) to 160 bits.
--typehashAlgoUse the specified cryptographic hash algorithm, which can be one of
blake3,md5,sha1,sha256, andsha512.--to-base16Don’t hash anything, but convert the Nix32 hash representation
hash to hexadecimal.--to-base32Don’t hash anything, but convert the hexadecimal hash representation
hash to Nix32.--to-base64Don’t hash anything, but convert the hexadecimal hash representation
hash to Base64.--to-sriDon’t hash anything, but convert the hexadecimal hash representation
hash to SRI.
Examples
Computing the same hash as nix-prefetch-url:
$ nix-prefetch-url file://<(echo test)
1lkgqb6fclns49861dwk9rzb6xnfkxbpws74mxnx01z9qyv1pjpj
$ nix-hash --type sha256 --flat --base32 <(echo test)
1lkgqb6fclns49861dwk9rzb6xnfkxbpws74mxnx01z9qyv1pjpjComputing hashes:
$ 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
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03Converting between hexadecimal, Nix32, Base64, and SRI:
$ 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=
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6Doc 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-rootpathSee the corresponding option in
nix-store.--parseJust parse the input files, and print their abstract syntax trees on
standard output as a Nix expression.--evalJust 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
--xmloption 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-fileLook up the given files in Nix’s search path (as specified by the
NIX_PATHenvironment variable). If found, print the corresponding
absolute paths on standard output. For instance, ifNIX_PATHisnixpkgs=/home/alice/nixpkgs, thennix-instantiate --find-file nixpkgs/default.nixwill print/home/alice/nixpkgs/default.nix.--strictWhen 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.--rawWhen used with
--eval, the evaluation result must be a string,
which is printed verbatim, without quoting, escaping or trailing newline.--jsonWhen used with
--eval, print the resulting value as an JSON
representation of the abstract syntax tree rather than as a Nix expression.--xmlWhen 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 thetoXML
built-in.--read-write-modeWhen 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:
$ 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:
$ nix-instantiate --expr 'with import <nixpkgs> { }; hello'
/nix/store/j8s4zyv75a724q38cb0r87rlczaiag4y-hello-2.8.drvThis is equivalent to:
$ nix-instantiate '<nixpkgs>' --attr helloParsing and evaluating Nix expressions:
$ nix-instantiate --parse --expr '1 + 2'
1 + 2$ nix-instantiate --eval --expr '1 + 2'
3$ 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:
$ 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
--typehashAlgoUse the specified cryptographic hash algorithm,
which can be one ofblake3,md5,sha1,sha256, andsha512.
The default issha256.--print-pathPrint the store path of the downloaded file on standard output.
--unpackUnpack 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’sfetchziporfetchFromGitHub.--executableSet the executable bit on the downloaded file.
--namenameOverride 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
$ nix-prefetch-url ftp://ftp.gnu.org/pub/gnu/hello/hello-2.10.tar.gz
0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i$ nix-prefetch-url --print-path mirror://gnu/hello/hello-2.10.tar.gz
0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i
/nix/store/8alrpdaasjd1x6g1fczchmzbpqm936a3-hello-2.10.tar.gz$ nix-prefetch-url --unpack --print-path https://github.com/NixOS/patchelf/archive/0.8.tar.gz
079agjlv0hrv7fxnx9ngipx14gyncbkllxrp9cccnh3a50fxcmy7
/nix/store/19zrmhm3m40xxaw81c8cqm6aljgrnwj2-0.8.tar.gzDoc 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
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 tonix-instantiate.
--commandcmdIn the environment of the derivation, run the shell command cmd.
This command is executed in an interactive shell. (Use--runto
use a non-interactive shell instead.) However, a call toexitis
implicitly added to the command, so the shell will exit after
running the command. To prevent this, addreturnat the end;
e.g.--command "echo Hello; return"will printHelloand then
drop you into the interactive shell. This can be useful for doing
any additional initialisation.--runcmdLike
--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.--excluderegexpDo not build any dependencies whose store path matches the regular
expression regexp. This option may be specified multiple times.--pureIf 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 particularHOME,USERandDISPLAY, are
retained. Note that the shell used to run commands is obtained fromNIX_BUILD_SHELL/<nixpkgs>fromNIX_PATH, and therefore not affected by--pure.--packages/-ppackages…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
nameslibjpegandopenjdkare present.-iinterpreterThe chained script interpreter to be invoked by
nix-shell. Only
applicable in#!-scripts (described below).--keepnameWhen a
--pureshell is started, keep the listed environment
variables.
{{#include ./opt-common.md}}
Environment variables
-
Shell used to start the interactive environment.
Defaults to thebashfrombashInteractivefound in<nixpkgs>, falling back to thebashfound inPATHif 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:
$ 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/panThe 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:
$ 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:
$ nix-shell --expr 'with import <nixpkgs> { }; runCommand "dummy" { buildInputs = [ sqlite xorg.libX11 ]; } ""'A shorter way to do the same is:
$ 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:
$ 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:
$ nix-shell --packages pan -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/8a3eea054838b55aca962c3fbde9c83c102b8bf2.tar.gz
[nix-shell:~]$ pan --version
Pan 0.139Use 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:
#! /usr/bin/env nix-shell
#! nix-shell -i real-interpreter --packages packageswhere 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 theprettytable package:
#! /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 andLWP::Protocol::Https packages:
#! /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:
#! /usr/bin/env nix-shell
#! nix-shell -i bash --packages 'terraform.withPlugins (plugins: [ plugins.openstack ])'
terraform applyNote
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):
#! /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:
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/0672315759b3e15e2121365f067c1c8c56bb4722.tar.gzThe 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:
#! /usr/bin/env nix-shell
#! nix-shell deps.nix -i pythonwhere the file deps.nix in the same directory as the #!-script
contains:
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:
--realise--serve--gc--delete--query--add--add-fixed--verify--verify-path--repair-path--dump--restore--export--import--optimise--read-log--dump-db--load-db--register-validity--print-env--generate-binary-cache-key
These pages can be viewed offline:
man nix-store-<operation>.Example:
man nix-store-realisenix-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:
-
Prints out a summary of the command syntax and exits.
-
Prints out the Nix version number on standard output and exits.
For machine-readable output, including versions of the libraries Nix
links against, see thenix versioncommand. --verbose/-vIncreases 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.
-
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-formatformatThis option can be used to change the output of the log format, with format being one of:
rawThis is the raw format, as outputted by nix-build.
internal-jsonOutputs the logs in a structured manner.
Warning
While the schema itself is relatively stable, the format of
the error-messages (namely of themsg-field) can change
between releases.barOnly display a progress bar during the builds.
bar-with-logsDisplay the raw logs, with the progress bar at the bottom.
--no-build-output/-QBy 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 inprefix/nix/var/log/nix.--max-jobs/-jnumberSets the maximum number of build jobs that Nix will perform in parallel to the specified number.
Specifyautoto use the number of CPUs in the system.
The default is specified by themax-jobsconfiguration setting, which itself defaults to1.
A higher value is useful on SMP systems or to exploit I/O latency.Setting it to
0disallows building on the local machine, which is useful when you want builds to happen only on remote builders.-
Sets the value of the
NIX_BUILD_CORESenvironment 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 attributeenableParallelBuildingis set totrue, the builder passes the-jNflag to GNU Make.
It defaults to the value of thecoresconfiguration setting, if set, or1otherwise.
The value0means that the builder should use all available CPU cores in the system. -
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 themax-silent-timeconfiguration setting.0means no time-out. -
Sets the maximum number of seconds that a builder can run.
The default is specified by thetimeoutconfiguration setting.0means no timeout. --keep-going/-kKeep 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/-KSpecifies 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.-
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). -
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. --argname valueThis option is accepted by
nix-env,nix-instantiate,nix-shellandnix-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.nixin 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 valuebuiltins.currentSystemfor thesystemargument.
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-filename pathPass the contents of file path as the argument name to Nix functions.
--arg-from-stdinnamePass the contents of stdin as the argument name to Nix functions.
--argstrname valueThis 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/-AattrPathSelect an attribute from the top-level Nix expression being evaluated.
(nix-env,nix-instantiate,nix-buildandnix-shellonly.)
The attribute path attrPath is a sequence of attribute names separated by dots.
For instance, given a top-level Nix expression e, the attribute pathxorg.xorgserverwould cause the expressione.xorg.xorgserverto be used.
Seenix-env --installfor some concrete examples.In addition to attribute names, you can also specify array indices.
For instance, the attribute pathfoo.3.barselects thebar
attribute of the fourth element of the array in thefooattribute
of the top-level expression.--eval-storestore-urlThe URL to the Nix store to use for evaluation, i.e. where to store derivations (
.drvfiles) and inputs referenced by them.--expr/-EInterpret 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-buildandnix-shellonly.)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 thenix-shell --packagesconvenience flag instead.-I/--includepathAdd an entry to the list of search paths used to resolve lookup paths.
This option may be given multiple times.Paths added through
-Itake precedence over thenix-pathconfiguration setting and theNIX_PATHenvironment variable.-
Allow access to mutable paths and repositories.
--optionname valueSet the Nix configuration option name to value.
This overrides settings in the Nix configuration file (see nix.conf5).-
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 undernix-store --repair-path.
Note
See
man nix.conffor 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:
100Generic build failureThe builder process returned with a non-zero exit code.
101Build timeoutThe build was aborted because it did not complete within the specified
timeout.102Hash mismatchThe build output was rejected because it does not match the
outputHashattribute of the derivation.104Not deterministicThe 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.
0b1100100
^^^^
|||`- timeout
||`-- output hash mismatch
|`--- build failure
`---- not deterministicDoc 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:
nix develop .#native-ccacheStdenvConfigure Build with Benchmarks
From the project root, configure the build with benchmarks enabled and optimization:
cd build
meson configure -Dbenchmarks=true -Dbuildtype=debugoptimizedThe 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:
ninjaThis 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:
./build/src/libstore-tests/nix-store-benchmarksAs more benchmark executables are added, run them similarly from their respective build directories.
Filtering Benchmarks
Run specific benchmarks using regex patterns:
# 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:
# 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.csvAdvanced Options
# 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=msWriting New Benchmarks
To add new benchmarks:
Create a new
.ccfile in the appropriate*-testsdirectoryInclude the benchmark header:
cpp#include <benchmark/benchmark.h>Write benchmark functions:
cppstatic void BM_YourBenchmark(benchmark::State & state) { // Setup code here for (auto _ : state) { // Code to benchmark } } BENCHMARK(BM_YourBenchmark);Add the file to the corresponding
meson.build:mesonbenchmarks_sources = files( 'your-benchmark.cc', # existing benchmarks... )
Profiling with Benchmarks
For deeper performance analysis, combine benchmarks with profiling tools:
# Using Linux perf
perf record ./build/src/libstore-tests/nix-store-benchmarks
perf reportUsing Valgrind Callgrind
Valgrind's callgrind tool provides detailed profiling information that can be visualized with kcachegrind:
# 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
# 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.jsonTroubleshooting
Benchmarks not building
Ensure benchmarks are enabled:
meson configure build | grep benchmarks
# Should show: benchmarks trueInconsistent 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.symlinksenabled, before cloning, as there are symlinks in the repo.
$ git clone https://github.com/NixOS/nix.git
$ cd nixNote
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:
$ nix-shellTo get a shell with one of the other supported compilation environments:
$ nix-shell --attr devShells.x86_64-linux.native-clangStdenvNote
You can use
native-ccacheStdenvto drastically improve rebuild time.
By default, ccache keeps artifacts in~/.cache/ccache/.
To build Nix itself in this shell:
[nix-shell]$ out="$(pwd)/outputs/out" dev=$out debug=$out mesonFlags+=" --prefix=${out}"
[nix-shell]$ dontAddPrefix=1 configurePhase
[nix-shell]$ buildPhaseTo test it:
[nix-shell]$ checkPhaseTo install it in $(pwd)/outputs:
[nix-shell]$ installPhase
[nix-shell]$ ./outputs/out/bin/nix --version
nix (Nix) 2.12To build a release version of Nix for the current operating system and CPU architecture:
$ nix-buildYou 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:
$ nix developThis 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:
$ nix develop .#native-clangStdenvNote
Use
ccacheStdenvto drastically improve rebuild time.
By default, ccache keeps artifacts in~/.cache/ccache/.
To build Nix itself in this shell:
[nix-shell]$ configurePhase
[nix-shell]$ buildPhaseTo test it:
[nix-shell]$ checkPhaseTo install it in $(pwd)/outputs:
[nix-shell]$ installPhase
[nix-shell]$ nix --version
nix (Nix) 2.12For more information on running and filtering tests, seetesting.md.
To build a release version of Nix for the current operating system and CPU architecture:
$ nix buildYou 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-linuxi686-linuxaarch64-linuxaarch64-darwinarmv6l-linuxarmv7l-linuxpowerpc64-linux(ELFv1 ABI)powerpc64le-linuxriscv64-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:
$ nix-build --attr packages.aarch64-linux.defaultor for Nix with the flakes and nix-command experimental features enabled:
$ nix build .#packages.aarch64-linux.defaultCross-compiled builds are available for:
armv6l-linuxarmv7l-linuxpowerpc64-linux(ELFv1 ABI)powerpc64le-linuxriscv64-linux
Add more system types tocrossSystemsinflake.nixto 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:
Instruct Nixpkgs's infra where we want Meson to put its build directory
bashmesonBuildDir=build-my-variant-nameConfigure as usual
bashconfigurePhaseBuild as usual
bashbuildPhase
System type
Nix uses a string with the following format to identify the system type or platform it runs on:
<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:
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-mingw32Compilation environments
Nix can be compiled using multiple environments:
stdenv: default;gccStdenv: force the use ofgcccompiler;clangStdenv: force the use ofclangcompiler;ccacheStdenv: enable [ccache], a compiler cache to speed up compilation.
To build with one of those environments, you can use
$ nix build .#nix-cli-ccacheStdenvfor flake-enabled Nix, or
$ nix-build --attr nix-cli-ccacheStdenvfor 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:
./maintainers/format.shPre-commit hooks
If you'd like to run the formatters before every commit, install the hooks:
pre-commit-hooks-installThis 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:
- Exit the development shell and start it again by running
nix develop. - If you also use the pre-commit hook, also run
pre-commit-hooks-installagain.
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.
{
"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 othernix commands.
$ nix [<GROUP>] <COMMAND> [<ARGUMENTS>] [<OPTIONS>]GROUP,COMMAND,ARGUMENTSandOPTIONSshould be lowercase and in a
singular form.GROUPshould be a NOUN.COMMANDshould be a VERB.ARGUMENTSandOPTIONSare 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:- Proper use of colors, emojis
and aligning of text. - Autocomplete of options.
- Show next possible steps.
- Showing some “tips” when running logs running tasks
(eg. building / downloading) in order to teach users interesting bits of
Nix ecosystem. - Help pages to be as good as we can write them
pointing to external documentation and tutorials for more.
Examples of such commands:
nix init,nix develop,nix build,nix run,
...- Proper use of colors, emojis
Infrequently used commands
From infrequently used commands we expect less attention to details, but
still some:- Proper use of colors, emojis
and aligning of text. - Autocomplete of options.
Examples of such commands:
nix edit,nix eval, ...- Proper use of colors, emojis
Utility and scripting commands
Commands that expose certain internal functionality of
nix, mostly used by
other scripts.- Autocomplete of options.
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
--helporhelpcommand (egnix--``helpornix help). - For non-COMMANDs (eg.
nix--``helpandnix 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--``helpornix help init) we display the
man page of that command. By default the PAGER is used (as ingit). - 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:
$ 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:
$ nix int
------------------------------------------------------------------------
Error! Command `int` not found.
------------------------------------------------------------------------
Did you mean:
|> nix init
|> nix inputSometimes 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.
$ 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-poetryNext 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:
$ 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 projectEducate 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.
$ 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 useARGUMENTS 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 oneARGUMENT. - With
OPTIONSit is possible to provide much better auto completion. - With
OPTIONSit is possible to provide much better error message. - Using
OPTIONSit 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 theCOMMANDS 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:
--colorsvs.--no-colors(showing colors in the output)--emojisvs.--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
$ 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 viaflake.nix we should prompt - for the first time - and let user review what is
going to happen.
$ 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] |> yOutput
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:
$ 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.
$ 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:
$ 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:
$ nix COMMAND
VERB_1 NOUN and other words
VERB__1 NOUN and other words
|> Some detailsFew 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:
$ 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>
------------------------------------------------------------------------Search
Use a fzf like fuzzy search when there are multiple options to choose from.
$ 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.
$ 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] |> yVerbosity
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.
---
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.
significance: significantSee also the format documentation.
Build process
Releases have a precomputed rl-MAJOR.MINOR.md, and no rl-next.md.
Branches
-
The main development branch. All changes are approved and merged here.
When developing a change, create a branch based on the latestmaster.Maintainers try to keep it in a release-worthy state.
-
These branches are the subject of backports only, and are
also kept in a release-worthy state. -
The latest patch release of the latest minor version.
-
Generally branches created by the backport action.
-
Branches that do not conform to the above patterns should be feature 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.hhheader.
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 astd::mapwith string keys.record: a fixed set of attributes each with their own type.
In C++, this would be represented by astruct.
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:
{
"local": { ... },
"remote": { ... },
"http": { ... }
}This is good, because the it is extensible at the root, and is somewhat self-documenting:
{
"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:
{ "outputs": [ "out" "bin" ] }However, simply converting everything to records is not enough, because the order of outputs must be preserved:
{ "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:
{ "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:
{
"foo": {}
}{
"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:
{ "foo": null }{ "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:
[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.
[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:
[nix-shell]$ nix-shell -p gdbOn macOS, use lldb:
[nix-shell]$ nix-shell -p lldbLaunching the Debugger
To debug the Nix binary, run:
[nix-shell]$ gdb --args ../outputs/out/bin/nixOn macOS, use lldb:
[nix-shell]$ lldb -- ../outputs/out/bin/nixUsing the Debugger
Inside the debugger, you can set breakpoints, run the program, and inspect variables.
(gdb) break main
(gdb) run <arguments>Refer to the GDB Documentation for comprehensive usage instructions.
On macOS, use 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:
nix-build -E '(import ./.).packages.${builtins.currentSystem}.nix.doc'or
nix build .#nix-manualand 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:
$ nix develop
$ mesonFlags="$mesonFlags -Ddoc-gen=true" mesonConfigurePhaseIf using direnv:
$ direnv allow
$ bash -c 'source $stdenv/setup && mesonFlags="$mesonFlags -Ddoc-gen=true" mesonConfigurePhase'Then build the manual:
$ cd build
$ meson compile manualThe 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.
Links and anchors
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
manand--helppages 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.When moving files, update redirects on nixos.org.
This is especially important when moving information out of the Nix manual to other resources.
When changing anchors, update client-side redirects
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:
textA [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-referenceUse 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:
$ nix build .#hydraJobs.internal-api-docs
$ xdg-open ./result/share/doc/nix/internal-api/html/index.htmlor inside nix-shell or nix develop:
$ configurePhase
$ ninja src/internal-api-docs/html
$ xdg-open src/internal-api-docs/html/index.htmlC 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:
$ nix build .#hydraJobs.external-api-docs
$ xdg-open ./result/share/doc/nix/external-api/html/index.htmlor inside nix-shell or nix develop:
$ configurePhase
$ ninja src/external-api-docs/html
$ xdg-open src/external-api-docs/html/index.htmlIf you use direnv, or otherwise want to run configurePhase in a transient shell, use:
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:
.------.
| 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:
$ nix develop .#native-clangStdenv
$ configurePhase
$ meson compile -C build clang-tidyThis will analyze all C++ source files and report any warnings.
To automatically apply fixes for certain warnings:
$ meson compile -C build clang-tidy-fixWarning
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:
- Builds all components with debug mode (for faster compilation)
- Runs clang-tidy on each component
- 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:
Inline suppression (preferred for specific cases):
cpp// NOLINTBEGIN(bugprone-some-check) ... code ... // NOLINTEND(bugprone-some-check)Or for a single line:
cppint x = something(); // NOLINT(bugprone-some-check)Configuration file (for project-wide suppression):
Add the check to the disabled list in.clang-tidy:yamlChecks: - -bugprone-some-check # Reason for disablingCheck options (for configuring check behavior):
yamlCheckOptions: bugprone-reserved-identifier.AllowedIdentifiers: '__some_identifier'
Adding new checks
To enable additional checks:
- Edit
nix-meson-build-support/common/clang-tidy/.clang-tidy - Add the check to the
Checkslist - Run clang-tidy locally to see the impact
- 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:
- Add the check implementation in
src/clang-tidy-plugin/ - Register it in
nix-clang-tidy-checks.cc - Enable it in
.clang-tidywith thenix-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:
# nix build .#hydraJobs.coverage
# xdg-open ./result/index.htmlExtensive 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
textsrc ├── 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:
-
This is used for finer-grained filtering of which tests to run.
-
This is used to avoid logging passing tests.
-
This is used to create a debugger breakpoint when an assertion failure occurs.
Putting the first two together, one might run
GTEST_BRIEF=1 GTEST_FILTER='ErrorTraceTest.*' meson test nix-expr-tests -vfor short but comprensive output.
Debugging tests
For debugging, it is useful to combine the third option above with Meson's --gdb flag:
GTEST_BRIEF=1 GTEST_FILTER='Group.my-failing-test' meson test nix-expr-tests --gdbThis will:
Run the unit test with GDB
Run just
Group.my-failing-testStop 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:
$ _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:
$ checkPhaseGrouping 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:
$ 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.17sRunning individual tests
Individual tests can be run with meson:
$ 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.txtThe --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:
$ 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:
foo
nix blah blub
baredit it like so:
foo
-nix blah blub
+gdb --args nix blah blub
barThen, 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:
$ 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:
_NIX_TEST_ACCEPT=1 meson test langThis 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:
nix build .#hydraJobs.tests.functional_userGenerally, 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++.
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
buildPhaseTo use an external fuzzing engine, set fuzzing-engine:
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:
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:
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/narsNote 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:
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.htmlIf 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.:
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if (path != computedPath)
throw FormatError(...);
#endifThe 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
testsjob generates installers for the platforms below and uploads them as an artifact:x86_64-linuxaarch64-darwin
The
installer_testjob (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:
Click into the detailed view of the CI run.
Scroll down to
Artifactssection.Download the corresponding installer artifact (
installer-darwinforaarch64-darwinandinstaller-linuxforx86_64-linux).Unpack the downloaded
.zipartifact.To generate an install command, plug the path to the unpacked artifact into this template:
consolesh <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.
git clone https://github.com/NixOS/nix.git
cd nix
meson setup build
cd build
ninja
(sudo) ninja installThe 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 fileprefix/etc/profile.d/nix.sh in your ~/.profile (or similar), like
this:
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
$ export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt
$ curl -L https://nixos.org/nix/install | shIn the shell profile and rc files (for example, /etc/bashrc,/etc/zshrc), add the following line:
export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crtNote
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:
ssl-cert-file = /etc/ssl/my-certificate-bundle.crtProxy 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
consoleerror: the user '_nixbld1' in the group 'nixbld' does not existwhen 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:
$ curl -L https://nixos.org/nix/install | shThis 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:
$ curl -L https://nixos.org/nix/install | sh -s -- --helpTo 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:
$ export VERSION=2.19.2
$ curl -L https://releases.nixos.org/nix/nix-$VERSION/install | shMulti 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:
$ bash <(curl -L https://nixos.org/nix/install) --daemonYou 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:
$ bash <(curl -L https://nixos.org/nix/install) --no-daemonIn 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:
$ su root
# mkdir /nix
# chown alice /nixInstalling from a binary tarball
You can also download a binary tarball that contains Nix and all its dependencies:
- Choose a version and system type
- Download and unpack the tarball
- Run the installer
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.confto direct macOS to create a "synthetic"
empty root directory to mount your volumespecify mount options for the volume in
/etc/fstabrw: read-writenoauto: 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:
$ 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:/# exitIf 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:
$ curl -L https://hydra.nixos.org/job/nix/master/dockerImage.x86_64-linux/latest/download/1 | docker load
$ docker run -ti nix:2.5pre20211105You can also build a Docker image from source yourself:
$ nix build ./\#hydraJobs.dockerImage.x86_64-linux
$ docker load -i ./result/image.tar.gz
$ docker run -ti nix:2.5pre20211105Docker 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:
$ 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-userDoc 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 innix.confcan 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:
$ 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; doneThis 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):
$ nix-daemonYou’ll want to put that line somewhere in your system’s boot scripts.
To let unprivileged users use the daemon, they should set theNIX_REMOTE environment variable todaemon. So you should put a line like
export NIX_REMOTE=daemoninto 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 callednix-users, do
$ chgrp nix-users /nix/var/nix/daemon-socket
$ chmod ug=rwx,o= /nix/var/nix/daemon-socketThis 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 callednix:
$ git clone https://github.com/NixOS/nixLikewise, 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-configto 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
libbrotliencandlibbrotlideclibraries 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, installpkgconfigand the Boehm garbage collector, and pass the option-Dlibexpr:gc=enabledtomeson setup.The
boostlibrary of version 1.87.0 or higher.
It can be obtained from the official web site https://www.boost.org/.The
editlinelibrary of version 1.14.0 or higher.
It can be obtained from the its repository https://github.com/troglobit/editline.The
libsodiumlibrary 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
libseccompis used to provide syscall filtering on Linux.
This is an optional dependency and can be disabled passing a-Dlibstore:seccomp-sandboxing=disabledoption to themeson setupcommand
(Not recommended unless your system doesn't supportlibseccomp).
To get the library, visit https://github.com/seccomp/libseccomp.On 64-bit x86 machines only,
libcpuidlibrary is used to determine which microarchitecture levels are supported
(e.g., as whether to havex86_64-v2-linuxamong 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=disabledoption tomeson setupscript.Unless
meson setup build -Dunit-tests=falseis 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 inprefix/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:
Remove the Nix daemon service:
consolesudo systemctl stop nix-daemon.service sudo systemctl disable nix-daemon.socket nix-daemon.service sudo systemctl daemon-reloadRemove files created by Nix:
consolesudo 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/nixRemove build users and their group:
consolefor i in $(seq 1 32); do sudo userdel nixbld$i done sudo groupdel nixbldThere may also be references to Nix in
/etc/bash.bashrc/etc/bashrc/etc/profile/etc/zsh/zshrc/etc/zshrc
which you may remove.
FreeBSD
Stop and remove the Nix daemon service:
consolesudo service nix-daemon stop sudo rm -f /usr/local/etc/rc.d/nix-daemon sudo sysrc -x nix_daemon_enableRemove files created by Nix:
consolesudo 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/nixRemove build users and their group:
consolefor i in $(seq 1 32); do sudo pw userdel nixbld$i done sudo pw groupdel nixbldThere 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
consoleerror: the user '_nixbld1' in the group 'nixbld' does not existwhen running Nix commands, refer to GitHub issue NixOS/nix#10892 for instructions to fix your installation without reinstalling.
If system-wide shell initialisation files haven't been altered since installing Nix, use the backups made by the installer:
consolesudo 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.bashrcOtherwise, edit
/etc/zshrc,/etc/bashrc, and/etc/bash.bashrcto remove the lines sourcingnix-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 NixStop and remove the Nix daemon services:
consolesudo 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.plistThis stops the Nix daemon and prevents it from being started next time you boot the system.
Remove the
nixbldgroup and the_nixbuildNusers:consolesudo dscl . -delete /Groups/nixbld for u in $(sudo dscl . -list /Users | grep _nixbld); do sudo dscl . -delete /Users/$u; doneThis will remove all the build users that no longer serve a purpose.
Edit fstab using
sudo vifsto remove the line mounting the Nix Store volume on/nix, which looks liketextUUID=<uuid> /nix apfs rw,noauto,nobrowse,suid,ownersor
textLABEL=Nix\040Store /nix apfs rw,nobrowseby setting the cursor on the respective line using the arrow keys, and pressing
dd, and then:wqto save the file.This will prevent automatic mounting of the Nix Store volume.
Edit
/etc/synthetic.confto remove thenixline.
If this is the only line in the file you can remove it entirely:bashif [ -f /etc/synthetic.conf ]; then if [ "$(cat /etc/synthetic.conf)" = "nix" ]; then sudo rm /etc/synthetic.conf else sudo vi /etc/synthetic.conf fi fiThis will prevent the creation of the empty
/nixdirectory.Remove the files Nix added to your system, except for the store:
consolesudo 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/nixRemove the Nix Store volume:
consolesudo diskutil apfs deleteVolume /nixThis 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:consolediskutil listIf you do find a "Nix Store" volume, delete it by running
diskutil apfs deleteVolumewith the store volume'sdiskXsYidentifier.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
/nixdirectory.
This is an expected sign of a successful uninstall.
The empty/nixdirectory 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/nixmountpoint.
Single User
To remove a single-user installation of Nix, run:
rm -rf /nix ~/.nix-channels ~/.nix-defexpr ~/.nix-profile ~/.local/share/nix ~/.local/state/nix ~/.cache/nixYou 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:
$ nix-shell -p nix -I nixpkgs=channel:nixpkgs-unstable --run "nix --version"
nix (Nix) 2.18.1Warning
Writing to the local store with a newer version of Nix, for example by building derivations with
nix-buildornix-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
$ sudo su
# nix-env --install --file '<nixpkgs>' --attr nix cacert -I nixpkgs=channel:nixpkgs-unstable
# systemctl daemon-reload
# systemctl restart nix-daemonmacOS multi-user
$ 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.plistSingle-user all platforms
$ nix-env --install --file '<nixpkgs>' --attr nix cacert -I nixpkgs=channel:nixpkgs-unstableDoc 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:nixderivation { ... exportReferencesGraph = [ "libfoo-graph" libfoo ]; };the references graph of
libfoois placed in the filelibfoo-graphin 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 havenixpassAsFile = ["big"]; big = "a very long string";then when the builder runs, the environment variable
bigPath
will contain the absolute path to a temporary file containinga very long string.[
__structuredAttrs]{#adv-attr-structuredAttrs}
If the special attribute__structuredAttrsis set totrue, 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 attributesallowedReferences,allowedRequisites,disallowedReferencesanddisallowedRequisites
will have no effect; useoutputChecksinstead.
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,nixallowedReferences = [];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,nixallowedRequisites = [ foobar ];enforces that the output of a derivation cannot have any other
runtime dependency thanfoobar, and in addition it enforces thatfoobaritself doesn't introduce any other dependency itself.[
disallowedReferences]{#adv-attr-disallowedReferences}
Specifies the disallowed references check. For example,nixdisallowedReferences = [ foo ];enforces that the output of a derivation cannot have a direct
runtime dependency on the derivationfoo.[
disallowedRequisites]{#adv-attr-disallowedRequisites}
Specifies the disallowed requisites check. For example,nixdisallowedRequisites = [ foobar ];enforces that the output of a derivation cannot have any runtime
dependency onfoobaror any other derivation depending recursively
onfoobar.[
outputChecks]{#adv-attr-outputChecks}
When using structured attributes, theoutputChecks
attribute allows defining checks per-output.In addition to
allowedReferences,allowedRequisites,disallowedReferencesanddisallowedRequisites,
the following attributes are available:maxSizespecifies the max size check.maxClosureSizespecifies the max closure size check.ignoreSelfRefscontrols the ignore self references behavior.
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
attributeunsafeDiscardReferencesis an attribute set with a boolean value for each output name.
If set totrue, 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 totrue, enables the prefer local build option.
This is useful for derivations that are cheapest to build locally.[
allowSubstitutes]{#adv-attr-allowSubstitutes}
If set tofalse, 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 itssystem-featuresconfiguration.For example, setting
nixrequiredSystemFeatures = [ "kvm" ];ensures that the derivation can only be built on a machine with the
kvmfeature.
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,fetchurlin Nixpkgs has the lineniximpureEnvVars = [ "http_proxy" "https_proxy" ... ];to make it use the proxy server configuration specified by the user
in the environment variableshttp_proxyand 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.
-
This is the default for
builtins.derivation.
Nix only currently supports one kind of input-addressing, so no other information is needed.__contentAddressed = false;may also be included, but is not needed, and will trigger the experimental feature check. -
All of
outputHash,outputHashAlgo, andoutputHashMode. (Floating) content-addressing derivations
Both
outputHashAlgoandoutputHashMode,__contentAddressed = true;, and notoutputHash.If an output hash was given, then the derivation output would be "fixed" not "floating".
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 [outputHashis also specified and includes its own hash algorithm as described below).The
outputHashModeattribute determines how the hash is computed.
It must be one of the following values:-
This is the default.
-
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. -
Warning
The use of this method for derivation outputs is part of the
dynamic-derivationsexperimental feature. -
Warning
This method is part of the
git-hashingexperimental 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 (unlessoutputHashis also specified and includes its own hash algorithm as described below).The
outputHashAlgoattribute specifies the hash algorithm used to compute the hash.
It can currently be"blake3","sha1","sha256","sha512", ornull.outputHashAlgocan only benullwhenoutputHashfollows the SRI format, because in that case the choice of hash algorithm is determined byoutputHash.outputHash{#adv-attr-outputHash}This will specify the output hash of the single output of a fixed-output derivation.
The
outputHashattribute 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
convertHashfunction shows how to convert between different encodings.
Thenix-hashcommand 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-derivationsexperimental feature.
For example, in nix.conf you could add:textextra-experimental-features = ca-derivationsThis 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:
derivationderivationStrictabortbaseNameOfbreakdirOffalsefetchGitfetchMercurialfetchTarballfetchTreefromTOMLimportisNullmapnullplaceholderremoveAttrsscopedImportthrowtoStringtrue
Tip
Should I use
builtinsorlib?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 Nixpkgslibcan improve, replace or deprecate those behaviors,
because its sources are pinned where reproducibility matters.So while it is not wrong to use
builtinsdirectly,
for instance in small Nixpkgs-independent projects,
you will have a better experience using a library likelibas 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).
[
name]{#attr-name} (String)A symbolic name for the derivation.
See derivation outputs for what this is affects.Example
nixderivation { 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:
nixderivation { # ... system = "x86_64-linux"; # ... }Example
Declare a derivation to be built on the system type that evaluates the expression:
nixderivation { # ... system = builtins.currentSystem; # ... }builtins.currentSystemhas the value of thesystemconfiguration 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/bashas the builder executable:nixderivation { # ... builder = "/bin/bash"; # ... };Example
Copy a local file to the Nix store for use as the builder executable:
nixderivation { # ... builder = ./builder.sh; # ... };Example
Use a file from another derivation as the builder executable:
nixlet pkgs = import <nixpkgs> {}; in derivation { # ... builder = "${pkgs.python}/bin/python"; # ... };[
args]{#attr-args} (List of String)Default:
[ ]See args.
Example
Pass arguments to Bash to interpret a shell command:
nixderivation { # ... 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 thebuilderexecutable 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:nixderivation { # ... outputs = [ "lib" "dev" "doc" ]; # ... }This will cause Nix to pass environment variables
lib,dev, anddocto the builder containing the intended store paths of each output.
The builder would typically do something likebash./configure \ --libdir=$lib/lib \ --includedir=$dev/include \ --docdir=$doc/share/docfor 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
nixderivation { 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 ofoutputsdetermines the default output and ends up at the top-level.Example
Select an output by attribute name:
nixlet myPackage = derivation { name = "example"; outputs = [ "lib" "dev" "doc" "out" ]; # ... }; in myPackage.devSince
libis the first output,myPackageis equivalent tomyPackage.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.trueis passed as the string1,falseandnullare
passed as an empty string.
- Constructing values from literals.
For example the number literal1is turned into the number value1. - 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 expressionbuiltins.isInt 1is evaluated totrue. - Applying user-defined functions
For example the expression(x: x + 1) 10can* be thought of rewritingxin the function body to the argument,10 + 1, which is then evaluated to11. - 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 (
-)
- Letters (
- Is not one of the keywords
importexprbuiltins.readFileexprbuiltins.readFileTypeexprbuiltins.readDirexprbuiltins.pathExistsexprbuiltins.filterSourcef exprbuiltins.path{ path = expr; }builtins.hashFilet exprbuiltins.scopedImport x drv- a user-defined function
- a built-in function
- an attribute set with a
__functorattribute - Division by zero
- Integer overflow, that is, any operation yielding a result outside of the representable range of Nix language integers
- 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. - 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.
- a
|>b is equivalent to b a - a
<|b is equivalent to a b 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.storePathcreates a string with a single constant string context element:nixbuiltins.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!nixbuiltins.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
exportReferencesGraphderivation 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.nixbuiltins.getContext (builtins.addDrvOutputDependencies (builtins.storePath "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv"))evaluates to
nix{ "/nix/store/fvchh9cvcr7kdla6n860hshchsba305w-hello-2.12.drv" = { allOutputs = true; }; }- Create a string with the desired string context elements.
(The contents of the string do not matter.) - Dump its context with
builtins.getContext. - Combine it with a base string and repeated
builtins.appendContextcalls. a string
a path
an attribute set that has a
__toStringattribute or anoutPathattribute__toStringmust be a function that takes the attribute set itself and returns a stringoutPathmust be a string
This includes derivation expressions or flake inputs (experimental).
- Double quote (
") - Backslash (
\) - Dollar sign followed by an opening curly bracket (
${) – "dollar-curly" $is escaped by prefixing it with two single quotes ('')''is escaped by prefixing it with one single quote (')- Linefeed (
\n):''\n - Carriage return (
\r):''\r - Tab (
\t):''\t xwith the value123, an integertextwith the value"Hello", a stringywhere the value is the result of applying the functionfto the attribute set{ bla = 456; }If a pattern is a single identifier, then the function matches any
argument. Example:nixlet negate = x: !x; concat = x: y: x + y; in if negate true then concat "foo" "bar" else ""Note that
concatis 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.,nixmap (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
functionnix{ x, y, z }: z + y + xcan only be called with a set containing exactly the attributes
x,yandz. No other attributes are allowed. If you want to allow
additional arguments, you can use an ellipsis (...):nix{ x, y, z, ... }: z + y + xThis 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 writingname ? e, where e is an arbitrary
expression. For example,nix{ x, y ? "foo", z ? "bar" }: z + y + xspecifies a function that only requires an attribute named
x, but
optionally acceptsyandz.An
@-pattern provides a means of referring to the whole value
being matched:nixargs@{ x, y, z, ... }: z + y + x + args.abut can also be written as:
nix{ x, y, z, ... } @ args: z + y + x + args.aHere
argsis 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 asa, usingargs.a, which was
given as an additional attribute to the function.Warning
args@binds the nameargsto the attribute set that is passed to the function.
In particular,argsdoes not include any default values specified with?in the function's set pattern.For instance
nixlet f = args@{ a ? 23, ... }: [ a args ]; in f {}is equivalent to
nixlet 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):nixlet 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:nixlet f = args@{ x ? args.a, ... }: x; in f { a = 1; }This evaluates to:
nix1This 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 thelocalServerargument set totruebut
thedb4argument set tonull, then the evaluation fails.Note that
->is the logical
implication
Boolean operation.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.This assertion says that in order for Subversion to have SSL support
(so that it can accesshttpsURLs), 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.)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-nullvalue was passed. This prevents an unnecessary rebuild of
Subversion if OpenSSL changes.Inline comments start with
#and run until the end of the line.Example
nix# A number 2 # Equals 1 + 1console2Block 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 */ */ 1consoleerror: syntax error, unexpected '*' at «string»:1:15: 1| /* /* nope */ * | ^Consider escaping nested comments and unescaping them in post-processing.
Example
nix/* /* nested *\/ */ 1console1- 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.
- text
Derive(...)For all stable derivations.
- text
DrvWithVersion(<version-string>, ...)The only
version-strings that are in use today are for experimental features:"xp-dyn-drv"for thedynamic-derivationsexperimental feature.
Outputs, input derivations, input sources, and environment variables appear in ascending order of their keys, with no duplicates.
The same holds of theoutput-namesnaming 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
inputDrvsentry is a derivation path, ending in.drv.There is no trailing content after the closing parenthesis.
There is no version header.
A masked derivation is only ever constructed once dynamic derivations have been resolved away, so it never needs one, andDrvWithVersion(...)does not occur.An
inputDrvskey is a hash rather than a store path, and its node is always the flatoutput-names— the nested form thedynamic-derivationsversion allows cannot appear, for the same reason.The store path name is the derivation name with
.drvsuffixed at the endIndeed, 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
name= the name of the store object.store-dir= the path of the store directorydigest= Nix32 representation of the compressed to 160 bits SHA-256 hash offingerprint.For the definition of the hash compression algorithm, please refer to section 5.1 of the Nix thesis.
- ebnf
fingerprint = type ":sha256:" inner-digest ":" store ":" nameNote 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>-name1and/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:selflabel to denote self-reference. - ebnf
| "output:" idFor 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:- "Flat"
- "Git"
- "Nix Archive" if the hash algorithm is not SHA-256.
idis 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 ofinner-fingerprint.
The base-16 encoding uses lower-cased hex digits.inner-fingerprint= one of the following based ontype: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 thetype="source:" ...case.
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
Optional
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:
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:
x: isAttrs x || isFunction xThe 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:
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:
let f = { ... }: "ok";
in f (throw "kablam")
=> error: kablamHowever, a set pattern does not add any strictness beyond WHNF of the attribute set argument.
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.
let x = x; in x
=> error: infinite recursion encounteredInfinite 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.
let f = x: f (x + 1);
in f 0
=> error: stack overflow; max-call-depth exceededStack 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:
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
orto 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
oris 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.
# IFD.nix
let
drv = derivation {
name = "hello";
builder = "/bin/sh";
args = [ "-c" "echo -n hello > $out" ];
system = builtins.currentSystem;
};
in "${builtins.readFile drv} world"nix-instantiate IFD.nix --eval --read-write-modebuilding '/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.
/* 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.
/* 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 [orexpr ]
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:
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
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
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
nixtrue && 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
nixtrue || 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
nixtrue -> false => false false -> throw "never evaluated" => true
Pipe operators
Example
textnix-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-operatorsexperimental feature
is enabled.
For example, include the following innix.conf:textextra-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:
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:
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
"--with-freetype2-library=" + freetype + "/lib"(where freetype is a derivation expression), you can instead write
"--with-freetype2-library=${freetype}/lib"The latter is automatically translated to the former.
A more complicated example (from the Nix expression for Qt):
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 GNUmake: 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
./. + "/" + foo + "-" + bar + ".nix"or
./. + "/${foo}-${bar}.nix"you can instead write
./${foo}-${bar}.nixAttribute name
Attribute names can be interpolated strings.
Example
nixlet name = "foo"; in { ${name} = 123; }text{ foo = 123; }
Attributes can be selected with interpolated strings.
Example
nixlet name = "foo"; in { foo = 123; }.${name}text123
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 fooReference 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
nixlet 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
nixlet 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
nixlet a = { outPath = "foo"; }; in "${a}"text"foo"
If both __toString and outPath are present in an attribute set, __toString takes precedence.
Example
nixlet a = { __toString = _: "yes"; outPath = throw "no"; }; in "${a}"text"yes"
If neither is present, an error is thrown.
Example
nixlet a = {}; in "${a}"texterror: 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 (\):
Example
nix"\""text"\""
Example
nix"\\"text"\\"
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:
''
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
"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:
Example
nix'' ''$ ''text"$\n"
Example
nix'' ''' ''text"''\n"
These special characters are escaped as follows:
''\ 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:
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 ashttp://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,
[ 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.,
[ 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:
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:
{ a = "Foo"; b = "Bar"; }.aThis evaluates to "Foo".
It is possible to provide a default value in an attribute selection using the or keyword.
Example:
{ a = "Foo"; b = "Bar"; }.c or "Xyzzy"{ 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:
{ "$!@#?" = 123; }."$!@#?"let bar = "bar"; in
{ "foo ${bar}" = 123; }."foo ${bar}"Both will evaluate to 123.
Attribute names support string interpolation:
let bar = "foo"; in
{ foo = 123; }.${bar}let bar = "foo"; in
{ ${bar} = 123; }.fooBoth 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:
{ ${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.,
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:
rec {
x = y;
y = 123;
}.xThis 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
rec {
x = y;
y = x;
}.xwill 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;]...inexpr
Example:
let
x = "foo";
y = "bar";
in x + yThis 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:
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:
let x = 123; in
{
inherit x;
y = 456;
}is equivalent to
let x = 123; in
{
x = x;
y = 456;
}and both evaluate to { x = 123; y = 456; }.
Note
This works because
xis added to the lexical scope by theletconstruct.
It is also possible to inherit attributes from another attribute set.
Example:
In this fragment from all-packages.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
...
inherit x y z;
inherit (src-set) a b c;
...is equivalent to
...
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
let
x = { a = 1; b = 2; };
inherit (builtins) attrNames;
in
{
names = attrNames x;
}is equivalent to
let
x = { a = 1; b = 2; };
in
{
names = builtins.attrNames x;
}both evaluate to { names = [ "a" "b" ]; }.
Functions
Functions have the following form:
pattern: bodyThe 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:
Note that functions do not have names. If you want to give them a name,
you can bind them to an attribute, e.g.,
let concat = { x, y }: x + y;
in concat { x = "foo"; y = "bar"; }Conditionals
Conditionals look like this:
if e1 then e2 else e3where 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:
assert e1; e2where 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:.
{ 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:
With-expressions
A with-expression,
with e1; e2introduces the set e1 into the lexical scope of the expression e2.
For instance,
let as = { x = "foo"; y = "bar"; };
in with as; x + yevaluates 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.,
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.
let a = 3; in with { a = 1; }; let a = 4; in with { a = 2; }; ...establishes the same scope as
let a = 1; in let a = 2; in let a = 3; in let a = 4; in ...Variables coming from outer with expressions are shadowed:
with { a = "outer"; };
with { a = "inner"; };
aDoes evaluate to "inner".
Comments
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.
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 anix replsession.
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:rto 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:
$ nix-env --install --attr nixpkgs.nix-serveYou can then start the server, listening for HTTP connections on
whatever port you like:
$ nix-serve -p 8080To check whether it works, try fetching the nix-cache-info file on the client:
$ curl http://avalon:8080/nix-cache-info
StoreDir: /nix/store
WantMassQuery: 1
Priority: 30When 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.:
$ 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:
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:
$ nix-env --delete-generations oldInstead of old you can also specify a list of generations, e.g.,
$ nix-env --delete-generations 10 11 14To delete all generations older than a specified number of days (except
the current generation), use the d suffix. For example,
$ nix-env --delete-generations 14ddeletes all generations older than two weeks.
After removing appropriate old generations you can run the garbage
collector as follows:
$ nix-store --gcThe behaviour of the garbage collector is affected by thekeep-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:
$ nix-store --gc --print-deadLikewise, 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
$ nix-collect-garbage -dis 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:
$ ln -s /nix/store/d718ef...-foo /nix/var/nix/gcroots/barThat 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
$ /nix/store/dpmvp969yhdq...-subversion-1.1.3/bin/svnevery time you want to run Subversion. Of course we could set up thePATH environment variable to include the bin directory of every
package we want to use, but this is not very convenient since changingPATH 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
$ nix-env --install --attr nixpkgs.subversionon 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
$ nix-env --install --attr nixpkgs.subversion nixpkgs.firefoxon 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:
$ 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-linkThis shows a profile called default. The file default itself is
actually a symlink that points to the current generation. When we do anix-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
$ nix-env --rollbackwhich 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:
$ nix-env --switch-generation 43which in this example would roll forward to generation 43 again. You can
also see all available generations:
$ nix-env --list-generationsYou 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:
$ nix-env --switch-profile /nix/var/nix/profiles/my-profile
$ nix-env --switch-profile /nix/var/nix/profiles/defaultThese 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):
$ nix-env --profile /nix/var/nix/profiles/other-profile --install --attr nixpkgs.subversionThis 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:
$ nix-env --install --attr nixpkgs.firefox --substituters ssh://alice@avalonThis 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 usessh-addto load
the decrypted private key intossh-agent.
You can also copy the closure of some store path, without installing it
into your profile, e.g.
$ nix-store --realise /nix/store/m85bxg…-firefox-34.0.5 --substituters
ssh://alice@avalonThis is essentially equivalent to doing
$ nix-copy-closure --from alice@avalon
/nix/store/m85bxg…-firefox-34.0.5You 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:
Match User nix-ssh
AllowAgentForwarding no
AllowTcpForwarding no
PermitTTY no
PermitTunnel no
X11Forwarding no
ForceCommand nix-store --serve
Match AllOn NixOS, you can accomplish the same by adding the following to yourconfiguration.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:
Grammar
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.
(* 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-pathis 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\storecontains backslashes, which must be escaped, making the leaf astring: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,versionand 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-formedstring— 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:
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:
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:
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:
masked-derivation = "Derive(" fields ")" ;
input-drv = "(" drv-hash "," output-names ")" ;
drv-hash = verbatim ; (* lowercase hexadecimal *)That is:
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:
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:
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 zThe 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
store-path = store-dir "/" digest "-" namewhere
Fingerprint
Inner fingerprint
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 inflake.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 toimmutable, as follows:
Link: <flakeref>; rel="immutable"(Note the required < and > characters around flakeref.)
flakeref must be a tarball flakeref. It can contain the tarball flake attributesnarHash, rev, revCount and lastModified. If narHash is included, its
value must be the NAR hash of the unpacked tarball (as computed vianix 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.
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:
https://<domain name>/<owner>/<repo>/archive/<reference or revision>.tar.gzExample
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 }: { /* ... */ }; }
[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.,