nix(1)

๐Ÿ‘‘ nix โ€” the manual, bestie edition ๐Ÿ’…

okay so you opened nix(1) from the General Commands Manual and you're about to get the whole entire tour. nix is THAT girl. let's go. ๐ŸŒธ

โš ๏ธ Warning โš ๏ธ this program is experimental and its interface is subject to change. like, yes she's iconic but she's also still growing. don't get too attached to any one flag, fr fr ๐Ÿ˜ญ

โœจ NAME โœจ

nix โ€” a tool for reproducible and declarative configuration management. that's the whole serve. reproducible means same inputs, same outputs, every time. declarative means you say what you want and nix figures out the how. main character energy tbh ๐Ÿซถ


๐ŸŒˆ SYNOPSIS ๐ŸŒˆ

nix [optionโ€ฆ] subcommand

where subcommand is one of the following, and bestie there are so many of them, so buckle up:

๐ŸŽ€ Help commands ๐ŸŽ€

  • nix help โ€” shows you help about nix itself, or about one specific subcommand if you point at one ๐Ÿ’–
  • nix help-stores โ€” shows you help about store types and all their settings ๐Ÿ“š

๐Ÿ”ฅ Main commands ๐Ÿ”ฅ

  • nix build โ€” builds a derivation, or fetches a store path ๐Ÿ—๏ธ
  • nix develop โ€” drops you into a bash shell with the build environment of a derivation, so you can poke around ๐Ÿš
  • nix flake โ€” manages Nix flakes (the cute self-contained project format) ๐Ÿฆ‹
  • nix profile โ€” manages Nix profiles ๐Ÿ‘›
  • nix run โ€” runs a Nix application, no install required โœจ
  • nix search โ€” searches for packages ๐Ÿ”

๐Ÿ”ฅ Main commands ๐Ÿ”ฅ

(no you're not seeing double, the original page literally labels this one "Main commands" again. iconic of it.) ๐Ÿ’€

  • nix repl โ€” starts an interactive environment for evaluating Nix expressions, aka the playground ๐ŸŽฎ

๐ŸŒŸ Infrequently used commands ๐ŸŒŸ

  • nix bundle โ€” bundles an application so it still works outside of the Nix store ๐Ÿ“ฆ
  • nix copy โ€” copies paths between Nix stores ๐Ÿšš
  • nix edit โ€” opens the Nix expression of a Nix package in $EDITOR โœ๏ธ
  • nix eval โ€” evaluates a Nix expression ๐Ÿงฎ
  • nix fmt โ€” reformats your code in the standard style ๐Ÿ’…
  • nix formatter โ€” builds or runs the formatter ๐ŸŽ€
  • nix log โ€” shows the build log of the specified packages or paths, if it's available ๐Ÿ“œ
  • nix path-info โ€” queries information about store paths ๐Ÿ”Ž
  • nix registry โ€” manages the flake registry ๐Ÿ—‚๏ธ
  • nix why-depends โ€” shows why a package has another package in its closure ๐Ÿค”

๐Ÿงš Utility/scripting commands ๐Ÿงš

  • nix config โ€” manipulates the Nix configuration โš™๏ธ
  • nix daemon โ€” a daemon that performs store operations on behalf of non-root clients ๐Ÿ‘ป
  • nix derivation โ€” works with derivations ๐Ÿ“
  • nix env โ€” manipulates the process environment ๐ŸŒ
  • nix hash โ€” computes and converts cryptographic hashes ๐Ÿ”
  • nix key โ€” generates and converts Nix signing keys ๐Ÿ”‘
  • nix nar โ€” creates or inspects NAR files ๐Ÿ—œ๏ธ
  • nix print-dev-env โ€” prints shell code that can be sourced by bash to reproduce the build environment of a derivation ๐Ÿ–จ๏ธ
  • nix store โ€” manipulates a Nix store ๐Ÿฌ

๐Ÿ› ๏ธ Commands for upgrading or troubleshooting your Nix installation ๐Ÿ› ๏ธ

  • nix upgrade-nix โ€” upgrades Nix to the latest stable version โฌ†๏ธ

๐Ÿ“ EXAMPLES ๐Ÿ“

okay real talk, seeing it in action hits different. here we go:

  • Create a new flake:
# nix flake new hello
# cd hello
  • Build the flake in the current directory:
# nix build
# ./result/bin/hello
Hello, world!
  • Run the flake in the current directory:
# nix run
Hello, world!
  • Start a development shell for hacking on this flake:
# nix develop
# unpackPhase
# cd hello-*
# configurePhase
# buildPhase
# ./hello
Hello, world!
# installPhase
# ../outputs/out/bin/hello
Hello, world!

like?? she built it, she ran it, she dev-shell'd it, she said Hello, world! four separate times. ate and left no crumbs ๐Ÿซถโœจ


๐Ÿ’œ DESCRIPTION ๐Ÿ’œ

Nix is a tool for building software, configurations and other artifacts in a reproducible and declarative way. for more information, see the Nix homepage or the Nix manual ๐ŸŒˆ


and that's only part one bestie, don't go anywhere โ€” part 2 is literally right there ๐Ÿ‘‘๐Ÿฆ‹

๐Ÿ‘‘ INSTALLABLES ๐Ÿ‘‘

โš ๏ธ WARNING: bestie. Installables are part of the unstable nix-command experimental feature. They are subject to change without notice. Do not build your whole personality on them. ๐Ÿ’€

So most nix subcommands are like "okay give me a thing to do stuff to" and that thing is an installable โ€” a command line argument that represents something realisable in the Nix store. โœจ

Here's the menu of installable types that most commands will accept:

  • Flake output attribute (experimental)
    • this is the default ๐ŸŽ€
  • Store path
    • Nix assumes this if the argument is a Nix store path, or a symlink pointing at one ๐Ÿ”—
  • Nix file, optionally qualified by an attribute path
    • you say so with --file/-f
  • Nix expression, optionally qualified by an attribute path
    • you say so with --expr

And here's the little shortcut that trips people up: for most commands, if you hand over no installable at all, . is assumed. That means Nix operates on the default flake output attribute of the flake sitting in your current directory. Yes, it's giving "I assumed you meant here." ๐Ÿซถ


๐ŸŒธ Flake output attribute

โš ๏ธ WARNING: Flake output attribute installables depend on both the flakes and nix-command experimental features, and they're subject to change without notice. Experimental era, babe. ๐Ÿงช

Example: nixpkgs#hello

These look like flakeref[#attrpath], where flakeref is a flake reference and attrpath is an optional attribute path. Wanna know more about flakes? Go read the nix flake manual page. Flake references are usually:

  • a flake identifier in the flake registry (e.g. nixpkgs) ๐ŸŒŸ
  • a raw path (e.g. /path/to/my-flake, or ., or ../foo) ๐Ÿ“
  • or a full URL (e.g. github:nixos/nixpkgs or path:.) ๐ŸŒ

When the flake reference is a raw path (a path with no URL scheme at all), Nix interprets it as a path: or git+file: url, like this:

  • If the path is within a Git repository, the url gets the form git+file://[GIT_REPO_ROOT]?dir=[RELATIVE_FLAKE_DIR_PATH] where GIT_REPO_ROOT is the path to the root of the git repository, and RELATIVE_FLAKE_DIR_PATH is the path (relative to the directory root) of the closest parent of the given path that contains a flake.nix within the git repository. If there's no such directory, Nix will error-out. ๐Ÿ˜ญ

Heads up: the search only includes files indexed by git. So files matched by .gitignore, or files that have never been git add-ed, will not be available in the flake. If that's not the vibe you want, specify path:<directory> explicitly.

So for example, if /foo/bar is a git repository with this structure:

.
โ””โ”€โ”€ baz
  โ”œโ”€โ”€ blah
  โ”‚   โ””โ”€โ”€ file.txt
  โ””โ”€โ”€ flake.nix

then /foo/bar/baz/blah will resolve to git+file:///foo/bar?dir=baz

  • If the supplied path is not a git repository, the url gets the form path:FLAKE_DIR_PATH where FLAKE_DIR_PATH is the closest parent of the supplied path that contains a flake.nix file (within the same file-system). If no such directory exists, Nix will error-out. ๐Ÿ’€

For example, if /foo/bar/flake.nix exists, then /foo/bar/baz/ will resolve to path:/foo/bar

Now, if attrpath is omitted, Nix tries some default values. For most subcommands the default is packages.system.default (e.g. packages.x86_64-linux.default), but some subcommands have other defaults. ๐Ÿ‘€

If attrpath is specified, it's interpreted as relative to one or more prefixes; for most subcommands those are packages.system, legacyPackages.*system* and the empty prefix. So on x86_64-linux, nix build nixpkgs#hello will try to build all three of these attributes:

  • packages.x86_64-linux.hello
  • legacyPackages.x86_64-linux.hello
  • hello

And if attrpath begins with . then no prefixes or defaults are attempted at all. That's what lets you write the form flakeref[#.attrpath], like github:NixOS/nixpkgs#.lib.fakeSha256, to avoid a search of packages.*system*.lib.fakeSha256. Slay, no more guessing. ๐Ÿ’…


๐ŸŽ€ Store path

Example: /nix/store/10l19qifk7hjjq47px8m2prqk1gv4isy-hello-2.10

These are paths inside the Nix store, or symlinks that resolve to a path in the Nix store. ๐ŸŒˆ

A store derivation is also addressed by store path.

Example: /nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv

If you wanna refer to an output path of that store derivation, add the output name preceded by a caret (^). โœจ

Example: /nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^out

And you can grab all outputs at once with the special syntax ^*. ๐Ÿ‘‘

Example: /nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^*


๐Ÿ’œ Nix file

Example: --file /path/to/nixpkgs hello

When the option -f / --file path [attrpathโ€ฆ] is given, installables are interpreted as the value of the expression in the Nix file at path. If attribute paths are provided, commands will operate on the corresponding values accessible at those paths. And here's the rule, no cap: the Nix expression in that file โ€” or any selected attribute โ€” must evaluate to a derivation. ๐Ÿ“œ


๐ŸŒŸ Nix expression

Example: --expr 'import <nixpkgs> {}' hello

When the option --expr expression [*attrpath*โ€ฆ] is given, installables are interpreted as the value of the of the Nix expression. (Yes, the original says "the value of the of the" โ€” we're keeping the facts, not fixing the prose, bestie. ๐Ÿ˜ญ) If attribute paths are provided, commands will operate on the corresponding values accessible at those paths. And again: the Nix expression, or any selected attribute, must evaluate to a derivation.

You may need to specify --impure if the expression references impure inputs (such as <nixpkgs>). ๐Ÿซง


๐Ÿฆ‹ Derivation output selection

Derivations can have multiple outputs, and each one corresponds to a different store path. For instance, a package can have a bin output with the programs in it, and a dev output that provides development artifacts like C/C++ header files. So which outputs do nix commands actually operate on? Great question, here's the tea: โ˜•

  • You can explicitly specify the desired outputs using the syntax installable^output1,โ€ฆ,outputN โ€” that is, a caret followed immediately by a comma-separated list of derivation outputs to select. For installables specified as Flake output attributes or Store paths, the output is specified in the same argument:

For example, you can obtain the dev and static outputs of the glibc package:

# nix build 'nixpkgs#glibc^dev,static'
# ls ./result-dev/include/ ./result-static/lib/
โ€ฆ

and likewise, using a store path to a "drv" file to specify the derivation:

# nix build '/nix/store/fpq78s2h8ffh66v2iy0q1838mhff06y8-glibc-2.33-78.drv^dev,static'
โ€ฆ

For --expr and -f/--file, the derivation output is specified as part of the attribute path:

$ nix build -f '<nixpkgs>' 'glibc^dev,static'
$ nix build --impure --expr 'import <nixpkgs> { }' 'glibc^dev,static'

This syntax is the same even if the actual attribute path is empty:

$ nix build --impure --expr 'let pkgs = import <nixpkgs> { }; in pkgs.glibc' '^dev,static'
  • You can also specify that all outputs should be used, with the syntax installable^*. For example, the following shows the size of all outputs of the glibc package in the binary cache:
# nix path-info --closure-size --eval-store auto --store https://cache.nixos.org 'nixpkgs#glibc^*'
/nix/store/i2fn2mjgihz960bwa7ldab5ra5fhxznh-glibc-2.33-123                 33208200
/nix/store/n2wnn3i47w6dbylh64hdjzgd5rrprdn8-glibc-2.33-123-bin             36142896
/nix/store/v7dyz518sbkzl8x2a1sgk1lwsfd3d6gm-glibc-2.33-123-debug          155787312
/nix/store/z4hv6ybyinqw9a3dwyl5k66a91aggylj-glibc-2.33-123-static          42488328
/nix/store/lrjirf0j1rjnvif6amyp9pfcqr2km385-glibc-2.33-123-dev             44200560

and likewise, using a store path to a "drv" file to specify the derivation:

# nix path-info --closure-size '/nix/store/fpq78s2h8ffh66v2iy0q1838mhff06y8-glibc-2.33-78.drv^*'
โ€ฆ
  • If you didn't specify the desired outputs, but the derivation has an attribute meta.outputsToInstall, Nix will use those outputs. For example, since the package nixpkgs#libxml2 has this attribute:
# nix eval 'nixpkgs#libxml2.meta.outputsToInstall'
[ "bin" "man" ]

a command like nix shell nixpkgs#libxml2 will provide only those two outputs by default. ๐ŸŽ

Note that a store derivation doesn't have any attributes like meta, and thus this case doesn't apply to it. ๐Ÿšซ

  • Otherwise, Nix will use all outputs of the derivation. ๐ŸŒˆ

๐Ÿช Nix stores

Most nix subcommands operate on a Nix store. The various store types are documented in the Store Types section of the manual. ๐Ÿ“š

The same information is also available from the nix help-stores command. Handy! โœจ


๐Ÿงš Shebang interpreter

The nix command can be used as a #! interpreter. Arguments to Nix can be passed on subsequent lines in the script. ๐Ÿช„

Verbatim strings may be passed in double backtick () quotes. Sequences of *n* backticks of 3 or longer are parsed as *n*-1 literal backticks. A single space before the closing is ignored if present.

--file and --expr resolve relative paths based on the script location. ๐Ÿ“

Examples:

#!/usr/bin/env nix
#! nix shell --file ``<nixpkgs>`` hello cowsay --command bash

hello | cowsay

or with flakes:

#!/usr/bin/env nix
#! nix shell nixpkgs#bash nixpkgs#hello nixpkgs#cowsay --command bash

hello | cowsay

or with an expression:

#! /usr/bin/env nix
#! nix shell --impure --expr ``
#! nix with (import (builtins.getFlake "nixpkgs") {});
#! nix terraform.withPlugins (plugins: [ plugins.openstack ])
#! nix ``
#! nix --command bash

terraform "$@"

or with cascading interpreters. Note that the #! nix lines don't need to follow after the first line, to accommodate other interpreters. ๐ŸŒ€

#!/usr/bin/env nix
//! ```cargo
//! [dependencies]
//! time = "0.1.25"
//! ```
/*
#!nix shell nixpkgs#rustc nixpkgs#rust-script nixpkgs#cargo --command rust-script
*/
fn main() {
    for argument in std::env::args().skip(1) {
        println!("{}", argument);
    };
    println!("{}", std::env::var("HOME").expect(""));
    println!("{}", time::now().rfc822z());
}
// vim: ft=rust

๐Ÿ’… OPTIONS ๐Ÿ’…

okay bestie, here's the part where we get into the knobs and switches โœจ every single one of these is a global flag, so they work basically everywhere, and you can just sprinkle them on like glitter ๐ŸŽ€


these are all about how much tea nix spills while it's working. more verbosity = more texts, more scrolling, more of you going "wait what happened" at 2am. pick your fighter ๐Ÿ’–

  • --debug โ€” cranks the logging verbosity level alllll the way up to debug. yes that's literally the name of the level. it's giving "I want to see everything" โœจ
  • --log-format format โ€” sets what the log output actually looks like. you pick exactly one of these four, no mixing and matching: raw, internal-json, bar, or bar-with-logs. choose wisely bestie ๐ŸŒธ
  • --print-build-logs, -L โ€” prints the full build logs straight to standard error. no hiding, no truncating, the whole thing ๐Ÿ“œ๐Ÿ’…
  • --quiet โ€” decreases the logging verbosity level. the "please stop telling me things, I'm overwhelmed" flag ๐Ÿคซ
  • --verbose, -v โ€” increases the logging verbosity level. stack it, spam it, watch the wall of text appear ๐Ÿ—ฃ๏ธ๐Ÿ”ฅ
ngl --quiet and --verbose are literally opposites and the way that they just nudge the level up or down is so simple it's iconic ๐Ÿ’œ

๐ŸŒˆ Miscellaneous global options ๐ŸŒˆ

the leftovers that don't fit anywhere else but are still lowkey essential. grab a snack ๐Ÿ“

  • --help โ€” shows you the usage information. the classic "hello, what are you" move ๐Ÿซถ
  • --offline โ€” disables substituters, and treats every previously downloaded file as up-to-date. it's giving airplane mode but for your store โœˆ๏ธ ngl this one is very useful when the wifi is acting up
  • --option name value โ€” sets the Nix configuration setting name to value, overriding nix.conf. two args, both required, no skipping ๐Ÿ‘‘
  • --refresh โ€” the chaotic sibling of --offline: it considers all previously downloaded files out-of-date instead. brb re-fetching everything ๐Ÿ”„๐Ÿ’€
  • --version โ€” shows the version information. short, sweet, slay โญ
note-ish moment: see man nix.conf for overriding configuration settings with command line flags. iykyk, that's where the real config lore lives ๐Ÿ“–โœจ

and that's the whole page, bestie, we made it to the end ๐Ÿ˜ญ๐ŸŽ‰ this nix(1) page comes straight from the Nix manual, and it's signed off all official with its own source, version and date down at the bottom โ€” think of it like the little copyright signature in a group photo, periodt ๐Ÿ’– no cap, go build something cute ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from