Installing Nix

Updated

September 12, 2026

Installing Nix

The rest of this book assumes a working Nix installation with flakes and the nix-command CLI enabled. The boring default is: a multi-user daemon install, flakes on, and nix run nixpkgs#hello succeeding before you write a single expression.

You do not need NixOS yet. Nix the package manager runs on ordinary Linux and on macOS. NixOS (the operating system) comes in the next chapter.

Mental model

Nix is three things that share a name:

Piece What it is
Nix the tool The nix binary and the nix-daemon that builds and substitutes store paths
The store /nix/store, a read-only tree of hashed paths
NixOS A Linux distribution whose entire system is a Nix derivation

This chapter installs the first two. The daemon (multi-user) install is the one that matches production: unprivileged users talk to nix-daemon over a socket; builds run as dedicated nixbld users; the store is owned by root.

Single-user installs (~/.nix-profile only, no daemon) exist. Skip them on a shared workstation. They fight SELinux, they fight /nix permissions, and they do not match the NixOS mental model you will use later.

Flakes are still marked experimental in some docs. On this book’s baseline (Nix 2.35+) they are the boring interface: flake.nix plus flake.lock, no ambient <nixpkgs> channel required.

curl installer
    │
    ▼
/nix created  +  nix-daemon enabled  +  your user in the trusted group
    │
    ▼
nix.conf: experimental-features = nix-command flakes
    │
    ▼
nix run nixpkgs#hello   →  "Hello, world!"

Worked examples

Case 1: Multi-user install on Linux

On a throwaway VM or a Linux workstation you control, run the official multi-user installer. Read the script. Then execute it:

curl -L https://nixos.org/nix/install -o nix-install.sh
less nix-install.sh
sh nix-install.sh --daemon

Output (abbreviated):

installing in multi-user mode...
alright! we're going to call sudo
copying Nix to /nix/store...
providing a `nix` command in your PATH...
setting up the nix-daemon systemd service...
Nix: just installed

Open a new login shell so PATH and NIX_PROFILES are set. Confirm:

nix --version
systemctl is-active nix-daemon

Output:

nix (Nix) 2.35.2
active

The daemon must be active. If it is not, systemctl enable --now nix-daemon and check journalctl -u nix-daemon.

Case 2: Enable flakes in nix.conf

The installer may already have turned flakes on. Check:

nix show-config | grep experimental-features

If the line does not include both nix-command and flakes, write them yourself.

On a multi-user install the file is /etc/nix/nix.conf (root). On a single-user leftover it is ~/.config/nix/nix.conf. Prefer the system file:

# /etc/nix/nix.conf
experimental-features = nix-command flakes

Restart the daemon so the change is picked up:

sudo systemctl restart nix-daemon

nix flake --help must print help, not an “experimental feature disabled” error.

On a multi-user machine the daemon reads /etc/nix/nix.conf. Putting flakes only in ~/.config/nix/nix.conf makes nix flake work in your shell and fail in nix-daemon builds (CI-shaped errors on the laptop). After editing the system file, systemctl restart nix-daemon.

26.05 NixOS ships daemon Nix 2.34. This book’s CLI baseline is 2.35+ (installer, or nix.package on NixOS). nix --version vs nixos-option nix.package — do not assume they match.

Case 3: First substitute from cache.nixos.org

You have not compiled anything. nix run should download a closure:

nix run nixpkgs#hello

Output:

copying path '/nix/store/…-hello-2.12.1' from 'https://cache.nixos.org'...
Hello, world!

If this compiles from source for minutes, your substituters are missing or unsigned. Confirm:

nix show-config | grep substituters

https://cache.nixos.org must be listed. The matching public key is shipped with Nix; you do not paste it by hand.

Case 4: A pinned flake instead of a floating channel

nix run nixpkgs#hello follows whatever nixpkgs your registry currently points at. That is fine for a smoke test. For desk work, pin.

Save as flake.nix in an empty directory:

# flake.nix
{
  description = "Desk smoke test";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";

  outputs = { self, nixpkgs }:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
    in
    {
      packages.${system}.default = pkgs.hello;
    };
}

If you are on aarch64, change system to "aarch64-linux" (or "aarch64-darwin" on Apple silicon).

nix flake lock
nix run

Output:

Hello, world!

flake.lock now pins the exact nixpkgs revision. Commit both files. The next machine that clones this directory gets the same hello.

Case 5: macOS (same daemon, different volume)

On macOS the installer creates an APFS volume for /nix (the root filesystem is signed and cannot hold /nix directly). Run the same official script with --daemon. After install:

nix --version
nix run nixpkgs#hello

Do not install Nix with Homebrew. Homebrew’s nix package fights the daemon, the volume, and the store layout. One installer, one /nix.

The trap

The trap is curl | sh without reading, then a second installer on top. Mixing the official installer, the Determinate installer, and a distro package (dnf install nix, apt install nix-bin) produces two daemons, two nix.conf files, and a store the next nix-collect-garbage is afraid to touch.

Pick one installer and keep it:

Situation Installer
Generic Linux VM, this book Official multi-user (--daemon)
Team that already standardised on Determinate Determinate, and only that
Fedora with a packaged nix you are required to use The distro package, then enable flakes by hand

If you already have a broken mix:

# last resort: uninstall, then one clean install
sudo systemctl stop nix-daemon
# follow the uninstall steps for whichever installer you actually used

Do not rm -rf /nix while a daemon is running.

A second trap is enabling flakes in ~/.config/nix/nix.conf while the daemon reads /etc/nix/nix.conf. Your shell says flakes are on; nix-build via the daemon says they are not. Put experimental-features in the file the daemon reads.

The boring rule

  • Multi-user daemon install. One /nix. One nix-daemon.
  • experimental-features = nix-command flakes in the daemon’s nix.conf.
  • Prove the install with nix run nixpkgs#hello substituting from cache.nixos.org, not compiling.
  • Pin nixpkgs in a flake.lock as soon as you keep the directory.
  • Do not stack installers. Do not install Nix via Homebrew.

Try this

  1. Run nix run nixpkgs#cowsay -- "desk online" and confirm the NAR came from cache.nixos.org (the “copying path … from” line).
  2. In Case 4’s directory, run nix flake metadata and write down the locked nixpkgs revision. Change nothing, run it on a second machine (or a container with Nix), and confirm the revision matches.
  3. Comment out experimental-features in nix.conf, restart the daemon, and run nix flake show. Restore the line after you have seen the error.
  4. Run ls -ld /nix /nix/store and note the owners. The store should not be writable by your ordinary user.