NixOS Immutable Linux
Nix projects disambiguation…
| Project | Description | 
|---|---|
| Nix (language) | Pure, lazy, functional declarative language used to express the composition declarations… | 
| Nix (Package Manager) | Purely functional package manager …builds without side-effects (reproducible) | 
| Nixpkgs | Standard package library for Nix …official definitions of a wide variety of software | 
| NixOS | Linux distribution which is built upon the Nix package manager | 
Nix language… just an executable…
- …~20MB program written in C++
- …programming language
- …package manager
- …method to compile software from source
- Nixpkgs…
- …a repository on GitHub
- …collection of Nix package derivations
- …90.000 plus reproducible software packages
 
- …uses Nix language and package manager
- …build from Nixpkgs collection
- …completely declerative
- …atomic system update …with rollback
- …configuration in a single file /etc/nixos/configuration.nix
- References…
- Package search nixos.org/packages
Use-cases…
- …reproducibility
- …software supply chain security
- …software bill of material (SBOM)
- …infrastructure as code
Install
Download NixOS and use the installer
Single user installation on any Linux distribution…
sudo mkdir /nix
sudo chown $USER:$USER /nix
sh <(curl -L https://nixos.org/nix/install) --no-daemon
source ~/.nix-profile/etc/profile.d/nix.sh
# unsinstall
rm -rf /nixNix Portable …Nix as a single binary…
- …permission-less …lives in $HOME/.nix-portable
- …installation-free …extracting archive on the release page
- …pre-configured …enable flakesandnix-commandout of the box
Configuration
System configuration…
- …/etc/nixos/configuration.nix
- …NixOS manual configuration section
# ...build the new configuration, make it the default
sudo nixos-rebuild switchUpgrade…
# ...upgrade NixOS to the latest version
sudo nixos-rebuild switch --upgradenix.conf
Nix configuration…
- /etc/nix/nix.conf…system defaults …modified with- configuration.nix
- $HOME/.config/nix/nix.conffor users
- $NIX_CONFIGoverwrite by environment variable
Documentation in the Nix Reference Manual
nix-channels
nixpkgs …global default package repository
- …one big Nix expression including derivations
- …each package is a derivation
- …package dependencies recursive derivation calls
Manage channels (unstable by default) with nix-channel:
https://nixos.wiki/wiki/Nix_channels
https://nixos.org/manual/nix/stable/#sec-channels
- A “channel” is a name for the latest “verified” git commits in Nixpkgs.
- Channel user will benefit from both verified commits and binary packages from the binary cache.
https://nixos.org/channels/
https://status.nixos.org/
https://channels.nix.gsc.io/
- stableconservative updates- only bug fixes and security patches
- release every six month
 
- unstablelatest updates, rolling basis
~/.nix-channels           # configuration
nix-channel --list        # current channelTo update the channel run:
nix-channel --update
nix-env -u  # upgrade all packages in the environment- Downloads the new Nix expressions (descriptions of the packages)
- Creates a new generation of the channels profile and unpack it under ~/.nix-defexpr/channels
Nix Store
Software is a graph of dependencies:
- …graphs typically implicit
- …Nix makes package graph explicit
/nix/store                # (directed acyclic) graph (database)
/nix/store/*              # nodes (immutable)- …(obviously) does not comply the Linux filesystem hierarchy standard (FHS)
- …packages can not conflict with one another
- …no package files across global directories like /libor/usr/lib
- …multiple versions of package coexist
Nodes
Nodes include references to paths in other nodes (edges).
- …each node is prefixed by a (unique) hash
- …for a given hash its contents is always identical across machines/platforms
- …can’t be modified after creation (immutable)
/nix/store/gv4rgr1p1dq5s4hx7ald6a7kli6p3xrz-firefox-85.0
           |                              | |
           |                              | `----------- name
           `------------------------------`------------- hashGraph
Query the nix store like a graph database:
# list run-time dependencies for derivation (i.e. Firefox)
nix-store --query --references $(which firefox)
# ^ recursive as tree
nix-store --query --tree $(which firefox)
# plot a graph
nix-store --query --graph $(which firefox) | dot -Tsvg
# save space by hardlinking store files
nix-store --optimise
# clean up storage
nix-store --gc
# see which result files prevent garbage collection
nix-store --gc --print-rootsDerivations
- Derivations recipe how to build other paths in the Nix store
- Special entries in the nix store /nix/store/*.drv
- Includes references to all dependency nodes
- Creates one or more entries in the Nix Store
 
- Special entries in the nix store 
- Derivation definition includes
- outputs- What nodes can this build
- inputDrvs- Other derivation that must be build before
- inputSrcs- Nodes already in the store on which this build depends
- platform- build platform
- builder- program to run for the build
- args- program argument list
- env- build environment
 
- Only contents referenced in the derivation available during build
- No implicit dependencies possible
- All dependencies made explicit
- All dependencies codified in the output hash
- Nothing is machine dependent (good for binary caching)
 
Build a derivation with nix-build:
nix-build /nix/store/lzha201i0b0d52rjxqlxbrximwf9bjiv-firefox-85.0.drvAny software build/install can be a binary download with no other prerequisites except the nix platform.
nix
Nix package manager…
- …similar to projects like rpmtree(used in Fedora Silverblue)
Needs to be enabled as experimental feature…
# ...for a user-space installation
>>> cat ~/.config/nix/nix.conf
experimental-features = nix-command flakes
# on a NixOS host-system
>>> cat /etc/nixos/configuration.nix
#...
nix.settings.experimental-features = "nix-command flakes"
#...
>>> sudo nixos-rebuld switchprofile
Manage nix profiles…
- …user default profile to ~/.nix-profile
- …links to packages in the Nix store
# ...install a package into the default profile...
nix profile install nixpkgs#neovim nixpkgs#fzf nixpkgs#jq
# ...list installed packages
nix profile list
# ...upgrade all packages
nix profile upgrade '.*'Rollback package management commands…
# ...list versions
nix profile history
# ...back to previous version
nix profile rollback
nix profile rollback --to $version
# ...remove past versions of a profile
nix profile wipe-historyMultiple profiles…
nix profile --profile ~/.another-profile install nixpkgs#gitsearch
nix search …packages
nix search                   # flake in current cirectory
nix search nixpkgs           # all available packages
nix search nixpkgs $name     # specific packagenix-env
Nix user environments…
- …synthesised view to the Nix store
- …sets of packages available to a user
- …different users have different environments
- …individual users can switch between different environments
 
- ~/.nix-profile…default user profiles- $NIX_PROFILE…overwrite by environment variable
- nix-env -S ~/my-profile…switch profile
 
Install and remove packages…
nix-env -q                # list installed derivations
nix-env -q --out-path     # ^ with absolute path
nix-env -qa 'name.*'      # list available packages
nix-env -i $name          # install package
nix-env -e $name          # un-install package
nix-env -u                # upgrade packages…rollback facilities rely on generations
nix-env --rollback
nix-env --list-generations
nix-env --switch-generation Install multiple packages…
cat > /tmp/packages.nix <<EOF
with import <nixpkgs>{};
[ htop moreutils ]
EOF
nix-env -if /tmp/packages.nixNix Language
- Very limited functionality except of executing derivations
- Lazy evaluated
- (Almost) free of side-effects
- no networking
- no user input
- no file writing
- no output (except traces)
 
- Builds done by other Nix tooling
A piece of Nix language code is a Nix expression…
- …evaluating a Nix expression produces a Nix value
- …content of a Nix file *.nixis a Nix expression
nix repl …start interactive interpreter for testing
Data types…
1                   # numbers
"a"                 # strings
[ "a" "b" ]         # lists
./README.md         # path literal (presence of / forward slash character)
{ a = 1; b = 2; }   # setFunctions…
x = arg: { a = arg; }
x = { arg1, arg2 }: {a = arg1; b = arg2; }let expression …create a binding…
- …;terminator …set definition
- …values only available for a single expression after the letkeyword
let x = 1; in x + x; # 2
let x = "abc"; y = "xyz"; in x + y; # "abcxyz"References
Media…
- What Nix Can Do, Matthew Croughan, SCaLE20x, 2023