What it is
Nix is a powerful package manager that enables reliable and reproducible builds and deployments across multiple systems, allowing you to install software without interfering with other packages.
Installation
Linux
sh <(curl -L https://nixos.org/install) --daemon
This command downloads and runs the official Nix installation script. The --daemon flag is recommended for system-wide installation. Follow the on-screen prompts for configuration.
macOS
sh <(curl -L https://nixos.org/install)
This command downloads and runs the official Nix installation script for macOS. It installs Nix to /nix by default.
Windows
Nix on Windows is experimental and typically requires WSL (Windows Subsystem for Linux).
- Install WSL 2.
- Open a WSL distribution (e.g., Ubuntu).
- Follow the Linux installation instructions within WSL:
sh <(curl -L https://nixos.org/install) --daemon
Core Concepts
- Nix Store (
/nix/store): All Nix packages and derivations are installed in the Nix store. Each package resides in its own unique directory named by its hash, ensuring isolation and immutability. Example:/nix/store/s0a3f11d84f1b4c30142241d37148232b-hello-2.10. - Derivations (
.drvfiles): These are build instructions that Nix executes. They describe how to build a package, including its dependencies, build scripts, and output. - Nix Expressions (
.nixfiles): These are Nix language files that define packages, configurations, or entire system environments. They are declarative and reproducible. - Nix Language: A purely functional, lazy programming language specifically designed for package management and system configuration.
- Channels: Mailing lists for Nix package sets. They provide a way to subscribe to updated sets of packages.
nixos-unstable,nixos-23.11are examples. - Nixpkgs: The main repository containing Nix expressions for a vast collection of software.
Commands / Usage
Managing Packages
-
Search for packages:
nix search nixpkgs firefoxSearches the configured Nix channels for packages matching "firefox".
-
Install a package (imperative, not recommended for reproducibility):
nix-env -iA nixpkgs.helloInstalls the
hellopackage from thenixpkgschannel into your user profile. -
Install multiple packages:
nix-env -iA nixpkgs.git nixpkgs.htopInstalls both
gitandhtopinto your user profile. -
Upgrade packages:
nix-env -uUpgrades all packages in your user profile to the latest versions available in your channels.
-
Upgrade specific packages:
nix-env -uA nixpkgs.firefoxUpgrades the
firefoxpackage in your user profile. -
List installed packages:
nix-env -qLists all packages currently installed in your user profile.
-
Uninstall a package:
nix-env -e helloRemoves the
hellopackage from your user profile. -
Rollback profile changes:
nix-env --rollbackReverts your user profile to the previous generation.
-
List profile generations:
nix-env --list-generationsShows a history of your user profile states, allowing you to switch between them.
-
Switch to a specific profile generation:
nix-env --switch-generation 5Switches your user profile to generation 5.
Managing Nix Channels
-
Add a channel:
nix-channel --add https://nixos.org/channels/nixos-unstable nixpkgsAdds the
nixos-unstablechannel and names itnixpkgs. -
Update channels:
nix-channel --updateFetches the latest package definitions from all subscribed channels.
-
List subscribed channels:
nix-channel --listShows all currently subscribed Nix channels.
Building and Managing Nix Expressions
-
Build a Nix expression (e.g., a package definition):
nix-build '<nixpkgs>' -A helloBuilds the
hellopackage from your Nixpkgs. The result is a symbolic link namedresultin the current directory pointing to the package in the Nix store. -
Build a specific Nix expression file:
nix-build ./my-package.nixBuilds the package defined in
my-package.nix. -
Enter a shell with a package available:
nix-shell -p helloStarts an interactive shell where the
hellopackage is available in thePATH. -
Enter a shell with multiple packages:
nix-shell -p git htop nodejsStarts an interactive shell with
git,htop, andnodejsavailable. -
Enter a shell defined by a Nix expression:
nix-shell ./shell.nixStarts an interactive shell based on the environment defined in
shell.nix. -
Build an environment from a Nix expression (e.g., for deployment):
nix-build --out-link ./my-deployment -E 'with import <nixpkgs> {}; runCommand "my-env" {} "mkdir -p $out/bin && cp $(cat pkgs.txt | xargs -I{} nix-build -A {} --no-out-link)/bin/* $out/bin"' --arg pkgs "{ hello = pkgs.hello; }"This is a more complex example demonstrating how to build a specific environment. A more common approach for reproducible environments is using
nix-shellor NixOS configurations. -
Evaluate a Nix expression:
nix-instantiate --eval --json '<nixpkgs>' -A helloEvaluates the Nix expression for the
hellopackage and prints its resulting Nix store path in JSON format. -
Run a command with specific packages:
nix-run -iA nixpkgs.cowsay 'cowsay "Hello Nix!"'Runs the
cowsaycommand with thecowsaypackage available.
Garbage Collection (Cleaning the Nix Store)
-
Delete unreferenced store paths:
nix-collect-garbageRemoves store paths that are no longer referenced by any garbage collection roots (e.g., user profiles, NixOS configurations).
-
Delete old profile generations:
nix-collect-garbage -dDeletes all but the latest generation of each profile, in addition to unreferenced store paths.
-
Delete unreferenced paths and old generations:
nix-collect-garbage --delete-oldRemoves all but the current generation of profiles and unreferenced store paths.
NixOS Specific (if using NixOS)
-
Rebuild NixOS system configuration:
sudo nixos-rebuild switchBuilds and activates the system configuration defined in
/etc/nixos/configuration.nix. -
Test NixOS system configuration:
sudo nixos-rebuild buildBuilds the system configuration without activating it, allowing you to test the build.
-
Rollback NixOS system configuration:
sudo nixos-rebuild switch --rollbackReverts the system to the previous configuration generation.
-
Boot into a previous NixOS generation: This is typically done via the bootloader menu (GRUB).
Common Patterns
-
Reproducible development environment: Create a
shell.nixfile:{ pkgs ? import <nixpkgs> {} }: pkgs.mkShell { buildInputs = [ pkgs.git pkgs.nodejs-18_x pkgs.yarn ]; shellHook = '' echo "Welcome to the reproducible development shell!" export MY_VAR="Hello from Nix!" ''; }Then run
nix-shellin the same directory to enter an environment withgit,nodejs-18_x, andyarnavailable. -
Installing a package without modifying your user profile:
nix-shell -p python3Packages.requestsThis opens a shell where
python3Packages.requestsis available. You can then run Python scripts that use this library. -
Building a project with specific dependencies:
nix-build '<nixpkgs>' -A python3Packages.buildPythonApplication '{ buildInputs = [ python3Packages.requests ]; src = ./.; installPhase = '' mkdir -p $out/lib/python3.11/site-packages cp -r $(echo ${python3Packages.requests}/lib/python3.11/site-packages/*) $out/lib/python3.11/site-packages/ cp my_script.py $out/bin/ ''; }'This example is illustrative; real package building is more complex and often uses
mkDerivation. -
Downloading a package’s source code:
nix-prefetch-url --unpack https://example.com/my-package-1.0.tar.gzDownloads and unpacks the source code for a given URL.
-
Finding the Nix store path of an installed package:
nix-env -q --out-path helloOutputs the Nix store path for the
hellopackage in your profile. -
Composing package sets:
# In a .nix file let commonPkgs = import <nixpkgs> { overlays = []; }; devPkgs = import <nixpkgs> { overlays = [ (self: super: { my-tool = super.callPackage ./my-tool.nix {}; }) ]; }; in devPkgs.my-toolThis shows how to create custom package sets or override existing ones.
Gotchas
- Imperative vs. Declarative: Using
nix-env -iis imperative and creates a user profile that is not easily reproducible. For reproducible environments, prefernix-shellwithshell.nixor NixOS configurations. - Channel Updates:
nix-channel --updateonly updates the metadata about packages. To actually install or build newer versions, you need to usenix-env -uor rebuild your Nix expression. - Garbage Collection: Nix does not automatically delete old or unreferenced packages. You must run
nix-collect-garbageperiodically to reclaim disk space. - Nix Store Path Hashing: The hash in Nix store paths is derived from the package’s dependencies, build instructions, and source. Changing any of these results in a new, distinct path, ensuring immutability.
- Build Failures: If a build fails, Nix will report the error. Debugging often involves entering the build environment using
nix-build --keep-failedand thennix-shellon the resulting.drvfile to manually inspect and fix the build script. - Nix Language Learning Curve: The Nix language is functional and can be unfamiliar. Many common patterns are available in Nixpkgs’
libmodule, but writing complex custom derivations might require learning more about the language. - Symlinks in
/run/current-systemon NixOS: On NixOS,/run/current-systemis a symlink to the current system generation in/nix/store. Do not modify files directly within/run/current-system; instead, modify yourconfiguration.nix.