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 /nix
Nix Portable …Nix as a single binary…
- …permission-less …lives in
$HOME/.nix-portable
- …installation-free …extracting archive on the release page
- …pre-configured …enable
flakes
andnix-command
out 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 switch
Upgrade…
# ...upgrade NixOS to the latest version
sudo nixos-rebuild switch --upgrade
nix.conf
Nix configuration…
/etc/nix/nix.conf
…system defaults …modified withconfiguration.nix
$HOME/.config/nix/nix.conf
for users$NIX_CONFIG
overwrite 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/
stable
conservative updates- only bug fixes and security patches
- release every six month
unstable
latest updates, rolling basis
~/.nix-channels # configuration
nix-channel --list # current channel
To 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
/lib
or/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 `------------------------------`------------- hash
Graph
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-roots
Derivations
- 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 buildinputDrvs
- Other derivation that must be build beforeinputSrcs
- Nodes already in the store on which this build dependsplatform
- build platformbuilder
- program to run for the buildargs
- program argument listenv
- 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.drv
Any 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 switch
profile
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-history
Multiple profiles…
nix profile --profile ~/.another-profile install nixpkgs#git
search
nix search
…packages
nix search # flake in current cirectory
nix search nixpkgs # all available packages
nix search nixpkgs $name # specific package
nix-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 variablenix-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.nix
Nix 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
*.nix
is 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; } # set
Functions…
arg: { a = arg; }
x = { arg1, arg2 }: {a = arg1; b = arg2; } x =
let
expression …create a binding…
- …
;
terminator …set definition - …values only available for a single expression after the
let
keyword
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