NixOS CLI

Paths

Executable sym

If a derivation is installed inside a user env

which git

/run/current-system/sw/bin/git

If a derivation is installed inside a NixOs profile

which chromium

/home/attila/.nix-profile/bin/chromium

however they are just sym links to the real executables inside store

which chromium | xargs realpath &&which git | xargs realpath

nix-channel

List channels

nix-channel --list
cat ~/.nix-channels
echo "Before adding a new channel:"
cat ~/.nix-channels
nix-channel --add https://nixos.org/channels/nixpkgs-stable newchan
echo "After adding a new channel:"
cat ~/.nix-channels
nix-channel --remove newchan
echo "After removing that new channel:"
cat ~/.nix-channels

Get channel generations

user channels

You can list user channel generations:

nix-env --list-generations -p /nix/var/nix/profiles/per-user/$USER/channels
22017-10-1122:58:46
32018-02-0521:45:40
42018-02-2517:58:02
52018-02-2518:11:58(current)

System channels

To system level channels are asociated with the root user, so you should use the some command as in the user channels section, but as root

nix-env --list-generations -p /nix/var/nix/profiles/per-user/$USER/channels

Update and rollback

Updating a channel is the declarative alternative to the procedurral apt update command of the Debian family, which updates your package index.

nix-channel --update nixpkgs
nix-env --list-generations -p /nix/var/nix/profiles/per-user/$USER/channels

However one notable difference that you can rollback to previous “repository states”

Note: You may need to change the generation variable to something else, and do not forget to change back to the newest state

nix-env --switch-generation $generation -p /nix/var/nix/profiles/per-user/$USER/channels
nix-env --list-generations -p /nix/var/nix/profiles/per-user/$USER/channels

Note: You can use nix-channel --rollback [generation] too, but it is not consistent with the concept, that channels states are simply stored in a profile

nix-env

Search available packages

There are two switch to available packages the -A to search only the top level nix-expressions

Use local nix expression as source

list all generations of the current profile

nix-env --list-generations

Rollback a generation

nix-env --rollback && nix-env --list-generations

Jump to the n-th generation

nix-env --switch-generation $n && nix-env --list-generations

List installed derivations in the current generation

nix-env --query

Effect other profile

You can command nix-env to operate on other profiles with the `-p` switch. It can be very usefull, since it is the olny way to operate on the system profile, becasue the defulat profile for root is still a user profile.

nix-env --list-generations -p /nix/var/nix/profiles/system

Delete old generations

Delete generations which are older then 9000 days

nix-env --delete-generations 9000d

nix-store

List all direct dependencies of a derivation

nix-store --query --references `which xterm`

List all dependencies of a derivation. (its closure)

nix-store --query --requisites  `which xterm`

List all reverse dependecies of a derivation

nix-store --query --referers `which node`

Print reference graph of a given executable/source path

nix-store --query --tree `which git`

Display reference graph of a given executable/source path

tmpFile=`mktemp`

nix-store -q --graph `which git` > tmpFile
if [ -s tmpFile  ];then

kgraphviewer tmpFile
fi

Get the size of a derivation

nix-store --query --size `which node`

Print garbage collector roots which contains a store path

nix-store --query --roots `which node`

NIX_PAT points to a nix expression (a directory with a default.nix in its root)

echo $NIX_PATH

IN_NIX_SHELL

1 if inside a nix shell environment, empty string otherwise

echo "IN_NIX_SHELL: $IN_NIX_SHELL"
nix-shell --command 'echo "IN_NIX_SHELL: $IN_NIX_SHELL"' nix-modules/default.nix

Nix as a language

Basics

Types

Available types

builtins.typeOf null # => "null"
builtins.typeOf 1 # => "int"
builtins.typeOf (-1) # => "int"
builtins.typeOf true # => "bool"
builtins.typeOf false # => "bool"
builtins.typeOf "foo" # => "string"
builtins.typeOf ''foo'' # => "string"
builtins.typeOf /tmp # => "path"
builtins.typeOf https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz # => "string"
builtins.typeOf {} # => "set"
builtins.typeOf [1 2 3] # => "list"
builtins.typeOf (x: y: x*y) # => "lambda"

Notes

  • Negative integers must be written inside parenthesis.
  • URLs are strings, regardless they are highlighted as path

Testing types

builtins.isInt 1 # => true
builtins.isBool true # => true
builtins.isBool false # => true
builtins.isString "foo" # => true
builtins.typeOf /tmp == "path" # => true
builtins.isAttrs {} # => true
builtins.isList [] # => true
builtins.isFunction (x: x*x) # => true
builtins.isInt "foo" # => false

Arthimetric operations

Basic operators

1 + 1
0 - 5
3 * 3
6 / 3

and since nix is functional language:

builtins.add 1 1
builtins.sub 0 5
builtins.mul 3 3
builtins.div 6 3

Using “/” in a literal will define it as

3/3

Logical operation

Logical AND

true  && true
true  && false
false && true
false && false

Logical OR

true  || true
true  || false
false || true
false || false

Logical XOR

There is no XOR operator, but it is easy to make a function:

xor = (p1: p2: (p1 || p2) && !(p1 && p2))
xor true true
xor true false
xor false true
xor false false

Logical implication

true  -> true
true  -> false
false -> true
false -> false

Varible binding and naming

Naming rules

Dash is supported in identifiets

first-num = 3
second-num = 5
first-num + second-num
let
  x = "foo";
  y = "bar";
in x + y

Inject attributes inside a collection using with

mySet = {foo = 3; bar = 4;}
with mySet; [foo bar]
with mySet; {foobar = foo + bar;}

Strings

String length

builtins.stringLength "foo bar"

Concat strings

builtins.concatStringsSep "/" ["nix" "var" "nix"]
var =  84 / 2
"The mining of life ${toString var}"
"The mining of life \${toString var}"

RegEx match

builtins.match "fx+" "foo"
builtins.match "fo+" "fooooo"
builtins.match "[[:space:]]+([[:upper:]]+)[[:space:]]+" "  FOO   "
builtins.match "a(b)(c)" "abc"

Replace in strings

builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar"

Split strings

builtins.split "([[:upper:]]+)" "  FOO   "

Lists

List length

builtins.length [1 2 3 4]

Test if list has a given element

builtins.elem 30 [10 20 30]
builtins.elem 40 [10 20 30]

Head and tail of lists

builtins.head [1 2 3]
builtins.tail [1 2 3]

Get/acces nth value from list

myList = ["foo" "bar" "foobar"]
builtins.elemAt myList 0
builtins.elemAt myList 2

Out of bound error:

myList = ["foo" "bar" "foobar"]
builtins.elemAt myList 3

Concat lists

builtins.concatLists [[1 2 3] [4 5 6] [7 8 9]]
[1 2 3] ++ [4 5 6] ++ [7 8 9]

“Append” lists

There is no built-in append function, but it is easy to implement using concatanation

append = (coll: val: coll ++ [val])
append [1 2] 3

map lists

builtins.map (x: x * x) [0 1 2 3 4]

Sort lists

builtins.sort builtins.lessThan [ 345 22 176 567 11 0 33 ]

any and all for lists

builtins.any (x : x < 10) [1 2 15]
builtins.any (x : x < 10) [16 11 20]
builtins.all (x : x < 10) [1 2 3]
builtins.all (x : x < 10) [1 2 50]

Filter lists

builtins.filter (x : x > 0) [33 (-12) 23 (-1)]

Folding / reduce

builtins.foldl' (coll: val: coll ++ [val]) [] [1 2 3 4 5 6]

Generate list (like ranges)

builtins.genList (x: x) 5
builtins.genList (x: x * x) 5

Sets

Inherit value from parent scope

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

String interpolation in attribute names

When the interpolation result is null, the attribute will not be added

yo = "foo"
{"bar${yo}" = 1; x = 2;}
{${if true then null else "no-this"} = 1; x = 2;}

List out Names/keys and values

builtins.attrNames { y = 1; x = "foo"; }
builtins.attrValues { y = 1; x = "foo"; }

Test if set contains name

mySet = { y = 1; x = "foo"; }
mySet ? x
mySet ? yo
builtins.hasAttr "x" mySet

get/acces set attribute

mySet = {foo = {yo = 24; }; bar = 12;}
mySet.bar
mySet.foo.yo
mySet.noSuchAValue or "fallback value"
builtins.getAttr "bar" mySet
if mySet ? foo.yo then mySet.foo.yo else "no such a value"
if mySet ? foo.yo then mySet.foo.yo else "no such a value"
if mySet ? foo.noName then mySet.foo.yo else "no such a value"

Remove attributes

It is not a problem if you try to remove a non existent attribute.

removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]

Merge sets

The latter set attributes take precedence, so on name collision they will be in the new set.

{foo = 4; bar = 7;} // {foo = 11; foobar = 14;}

List to set

builtins.listToAttrs [{name = "x"; value = 2;} {name = "y"; value = 4;}]

Recursive sets

A recursive set values can reference each other, regardless of their literal order, but not circularly, obviously…

rec {x = 4; x2 = x * x;}
rec {x2 = x * x; x = 4;}

Union of sets

{foo = 3; bar = 4;} // {foo = 15; yo = 42;}

Intersection of sets

Intersect two sets by attributes, the values of the latter set take precedence.

builtins.intersectAttrs {foo = 3; bar = 4;} {foo = 15; yo = 42;}

set funcotors

let add = { __functor = self: x: x + self.x; };
    inc = add // { x = 5; };
in inc 2

Practical example

let add = { __functor = self: x: builtins.concatStringsSep "" [self.prefix x]; };
    urls = add // { prefix = "https://"; };
in urls "wikipedia.org"

Control flow

if then else

if true then "foo" else "bar"

Assertion

assert true; "works"

It throws error if the first expression evaluates false.

assert false; "error"

Exit/abort print error message

throw errors can be skipped by nix-env -qa, when it evaluates a set of derivations, abort on the other hand will certanly exit

1 + 2
throw "Error msg"
abort "Error msg"
2 + 3

Sequential evaluation

builtins.seq (3 == 3) (2 + 3)
builtins.seq (3 == 2) (2 + 3)

Deep sequential evaluation

builtins.deepSeq [(2 - 1) (3 + 4)] (3 - 4)

Functional programming

function definition

There is three different function definition pattern

identifier pattern
add = x: y: x + y
add 1 2
set pattern, which lets you define default values
add = {x, y ? 1}: x + y
add {x = 1; y = 2;}
add {x = 1;}
@ pattern which give you acces to the set of arguments
add = {x, y} @ args: args // { sum = x + y;}
add {x = 1; y = 2;}

Default function arguments

({ x, y ? "No y"}: y) {x = 1; y = 2;}
({ x, y ? "No y"}: y) {x = 1;}

However passing a set with an attribute not expected by the function will throw an error.

({ x, y ? "No y"}: y) {x = 1; z = 2;}

Currying/partial

doubleIt = (builtins.mul 2)
builtins.typeOf doubleIt
doubleIt 7

Get function argument set attributes

The returned set will hold the attributes name, their value be true if they are defaulted, false otherwise.

builtins.functionArgs  ({ x, y ? 123}: 42)

Paths

Basename

baseNameOf /tmp/foo/bar
builtins.dirOf /tmp/test

Path exists

builtins.pathExists /dev
builtins.pathExists /no/path/like/this/name

Read directory

builtins.readDir ''/home/${builtins.getEnv "USER"}''

possible types are directory, regular, symlink and unknown for device files.

Versions

compare versions

builtins.compareVersions "1.0.0" "1.0.0" # =>  0
builtins.compareVersions "1.0.1" "1.0.0" # =>  1
builtins.compareVersions "1.0.0" "1.0.1" # => -1

Split strings to package name and version

builtins.parseDrvName "node-8.9.1"
builtins.parseDrvName "nix-0.12pre12876"

modules

import nix-modules/simple-expression.nix
rec {x = 42; y = import nix-modules/expression-require-argument.nix x;}
import nix-modules/expression-require-set.nix {x = 3; y = 5;}

Debug

builtins.trace (builtins.concatLists [["debug"] [" info"]]) (1 + 5)

Interoperation

Environment

Get environmental variables

builtins.getEnv "USER"
builtins.getEnv "NO_ENV_LIKE_THIS"

System

Get system type

builtins.currentSystem
builtins.toFile "file-name.txt" "content of the file"

Read file

builtins.readFile nix-modules/simple-expression.nix

Network

Fetch tarball

fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz

Fetch URL

It will return the path of the downloaded file

builtins.fetchurl http://example.org/

Decode JSON

builtins.fromJSON ''{"x": [1, 2, 3], "y": null}''

Encode JSON

builtins.toJSON {foo = {bar = 1; foobar = 2;}; yo=3;}

Encode XML

builtins.toXML {foo = 3;}
builtins.toXML "foo bar"
builtins.toXML builtins.div

Derivations

String to hash string

builtins.hashString "md5" "foo"
builtins.hashString "sha1" "foo"
builtins.hashString "sha256" "foo"