Nix¶
Basic design¶
Nix installs packages in /nix/store; each package “version” has its own subdirectory, and the name includes a hash over the build inputs. That way multiple versions of the same package can be installed at the same time.
Each package can use specific versions (reference by their name in /nix/store) of other packages (e.g. dynamically linked libraries). This is very similar to docker (“immutable image containing all dependencies”), but makes better use of disk space (and downloads), as many packages can share dependencies, and doesn’t need a mount namespace to run programs (and no volume mappings and so on to access your files).
NixOS¶
Nix can be used as main OS or just to install additional packages.
nixos-rebuild builds a set of packages with a fixed configuration (into a system “profile”); configuration changes require a rebuild.
Binary Caches¶
Packages are actually “derivations” - instructions how to create a binary from specific sources. Binary caches provide prebuild binaries of those derivations.
Using a binary cache implies trusting it (the configuration uses GPG keys to sign the binaries).
The default cache is at https://cache.nixos.org/.
Generations and garbage collection¶
Profiles (both from nix-env and nixos-rebuild) and channels use “generations”; every update will create a new generation, allowing an easy rollback to the previous generation.
Those profiles and so on need to live in well-known places (“gcroots”) so the garbage collector knows what to keep.
nix-collect-garbage seems to be the proper command to cleanup old generations and unreferenced packages.
Multi-User¶
As packages are immutable and profiles reference explicit package versions, there is no risk (apart from disk space abuse) allowing users to install packages (and updating just means installing new versions) - no other user will be affected by it.
Users allowed to install packages (i.e. use nix-env) must be added to the nix-users group (which protects the nix-daemon socket in /nix/var/nix/daemon-socket/), and nix-daemon must be run.
Note
SUID binaries (and binaries using capabilities) like sudo and ping are not supported in /nix/ for security reasons.
In NixOS they are provided through wrappers in /run/wrappers.
nix-channel¶
Channels are the main source of packages. Updating a channel doesn’t update packages; you need to update the profiles too.
Channels use an alias (that is used to install packages) and point to an URL.
Info
- Status of recently updated (i.e. “supported”) channels: https://status.nixos.org/
- List of all upstream channels: https://nixos.org/channels
- Differences between channels: https://discourse.nixos.org/t/differences-between-nix-channels/13998
- Latest:
nixpkgs-unstable - Rolling unstable NixOS:
nixos-unstable- should have less versions of a single package thannixpkgs-unstable, i.e. use less disk space - Latest stable:
nixos-xx.yy- released every 6 months, receives updates for 7 months. - All upstream channels are released from https://github.com/NixOS/nixpkgs - the
nixos-*channels are stillnixpkgs, just different versions.
Various tools expect nixpkgs to be available as channel alias; if you don’t want to use nixpkgs-unstable consider adding a different upstream channel as nixpkgs.
Warning
A channel (alias) should be either added as root or as user, not both.
You can only update (and list) your own channels, but users can use channels added by root.
nix-channel --add https://nixos.org/channels/nixos-unstable nixpkgs
nix-channel --add https://nixos.org/channels/nixos-23.05 nixos
nix-env¶
nix-env can be used to manage “profiles”; each user can have a default profile (~/.nix-profile symlink, defaults to /nix/var/nix/profiles/per-user/${USER}/profile), and you should add ~/.nix-profile/bin to your $PATH to make installed binaries available.
Note
On debian you might want to symlink /usr/share/doc/nix-bin/examples/nix-profile.sh into /etc/profile.d/ to add ~/.nix-profile/bin to $PATH for all users.
- install packages with
nix-env --install --prebuilt-only --attr ${channelalias}.${package} - upgrade profile:
nix-env --upgrade --prebuilt-onlyThis builds a new “generation” of the profile; you can go back to the previous one withnix-env --rollback. - list installed packages with
nix-env --queryThis only lists the “top-level” (installed) packages, not the dependencies.
Warning
[nix-env] uses way too much memory in various cases: https://github.com/NixOS/nixpkgs/issues/38635
- use https://search.nixos.org/packages to search for packages instead of
nix-env --query --available - use
nix-env --install --attr ${channelalias}.${package}to install packages instead ofnix-env --install ${package}
Hint
To avoid compiling packages locally use --prebuilt-only for --install and --upgrade operations.
custom profiles¶
nix-env supports a --profile option to manage profiles in other locations than ~/.nix-profile.
To make sure the garbage collector sees the profile normal users should put those in /nix/var/nix/profiles/per-user/${USER}/${profile}.
Note
The experimental nix profile seems to put those profiles into ~/.local/state/nix/profiles/ - unclear how the garage collector finds those.
You can then either switch your ~/.nix-profile symlink to a custom profile, or call commands from /nix/var/nix/profiles/per-user/${USER}/${profile}/bin directly (or add it to your $PATH).
Example:
nix-env --profile "/nix/var/nix/profiles/per-user/${USER}/syncthing" --install --prebuilt-only --attr nixos.syncthing
systemctl --user enable "/nix/var/nix/profiles/per-user/${USER}/syncthing/lib/systemd/user/syncthing.service"
systemctl --user start syncthing.service
nix-env --profile /nix/var/nix/profiles/per-user/${USER}/syncthing --upgrade --prebuilt-only
systemctl --user daemon-reload
systemctl --user restart syncthing.service
nix-shell -p ...¶
nix-shell can be used to quickly spawn shells with binaries from specified packages in $PATH.
nix-shell doesn’t maintain anything that would keep installed packages alive when the garbage collector is run.
Note
It seems nix-shell is hardcoded to use the nixpkgs channel.
If you don’t use nixpkgs-unstable (which defaults to a nixpkgs alias) you might either add some nixos-* channel with nixpkgs alias or use somethine like NIX_PATH=nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos nix-shell ... to temporarily alias it to some other channel.
Flakes¶
Flakes are an alternative to channels. They are built such that one flake can depend on others.
Note
Flakes are experimental and need to be enabled like this:
A flake is a nix expression of an attribute set in flake.nix in a directory (usually from a git repository), with a specific set of attributes.
A flake can list various inputs (using https://github.com/NixOS/flake-registry to find them by default); those are directories containing flakes again or any other nix expression in default.nix.
Flakes are designed to be “pure”; they currently don’t know the platform they are used on, and must contain definitions for all platforms they support. See flake-utils to help with this.