TL;DR — Quick Summary

Nix is a purely functional package manager enabling reproducible builds and system configurations. Learn installation, flakes, dev shells, and NixOS basics.

Nix is a purely functional package manager that takes a fundamentally different approach to package management. Instead of modifying global system state, every package is built in complete isolation with its exact dependencies specified. This makes builds reproducible, rollbacks trivial, and multiple versions of the same software coexistable. This guide covers Nix from installation through real-world workflows.

Prerequisites

  • Linux (any distribution) or macOS
  • ~10 GB free disk space (Nix store grows over time)
  • curl for installation
  • Basic command-line familiarity

Why Nix?

Traditional package managers like apt, dnf, and brew modify global system state. Installing a package changes shared libraries, updates global paths, and can break other software. Nix solves this fundamentally:

  • Reproducibility: The same package definition always produces the exact same output
  • Isolation: Every package has its own dependency tree — no DLL/shared library conflicts
  • Atomic upgrades: Upgrades either complete fully or not at all — no broken intermediate states
  • Rollback: Instantly revert to any previous system generation
  • Multi-version: Run Python 3.10 and 3.12 simultaneously without containerization

Installation

curl --proto '=https' --tlsv1.2 -sSf -L \
  https://install.determinate.systems/nix | sh -s -- install

This enables flakes and the new CLI by default, uses systemd for the daemon, and provides an uninstaller.

Official Installer

sh <(curl -L https://nixos.org/nix/install) --daemon

After installation, open a new terminal or source the profile:

. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh

Core Concepts

The Nix Store

Every package is stored at /nix/store/<hash>-<name>-<version>/. The hash incorporates all inputs (source, dependencies, build flags), ensuring that any change produces a different path:

/nix/store/a1b2c3d4...-nodejs-22.0.0/
/nix/store/e5f6g7h8...-nodejs-20.0.0/

Both versions coexist without conflict.

Searching and Installing Packages

# Search for packages (90,000+ available)
nix search nixpkgs nodejs
nix search nixpkgs ripgrep

# Install to user profile
nix profile install nixpkgs#nodejs_22
nix profile install nixpkgs#ripgrep

# Temporary shell with a package (no install)
nix shell nixpkgs#python312 nixpkgs#poetry

Nix Flakes for Projects

Flakes are the modern way to use Nix. Create flake.nix in your project root:

{
  description = "My web application";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in {
        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [
            nodejs_22
            nodePackages.pnpm
            postgresql_16
            redis
            just
          ];

          shellHook = ''
            echo "Development environment ready!"
            echo "Node: $(node --version)"
          '';
        };
      });
}

Enter the development shell:

nix develop     # Enter the shell with all tools
nix develop -c just build  # Run a single command in the shell

The flake.lock file pins exact versions. Commit it for team-wide reproducibility.

Comparison

FeatureNixapt/dnfHomebrewDockerConda
ReproducibilityExcellentPoorFairGoodFair
Multi-versionNativeDifficultDifficultContainersEnvironments
RollbackNativeManualManualRebuildManual
Cross-platformLinux + macOSLinux onlymacOS + LinuxAnywhereAnywhere
Learning curveSteepEasyEasyMediumMedium
Package count90,000+60,000+7,000+N/A20,000+

Real-World Scenario

Your CI pipeline uses Ubuntu 22.04 with Node 18, but a developer on macOS has Node 20, and another uses Fedora with Node 22. Tests pass locally but fail in CI. With a flake.nix, all three developers and CI use the exact same Node version, same native dependencies, same tool versions. Running nix develop on any machine produces an identical environment — no Dockerfile needed, near-zero startup time.

Gotchas

  • Disk usage: The Nix store grows over time. Run nix store gc periodically to clean unused packages
  • Learning curve: The Nix language is functional and unfamiliar to most developers. Start with nix shell and nix develop before diving into the language
  • Binary caches: Nix downloads pre-built binaries from cache.nixos.org by default. Without cache hits, packages build from source (slow). Use Cachix for custom binary caches
  • macOS quirks: Some packages need Xcode command line tools. Run xcode-select --install before installing Nix on macOS
  • Flakes are experimental: While widely used, flakes remain behind an experimental flag in the official installer. The Determinate Systems installer enables them by default

Troubleshooting

  • Command not found after install: Open a new terminal or run . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
  • Permission denied in /nix/store: The Nix daemon must be running. Check with systemctl status nix-daemon and start with sudo systemctl start nix-daemon
  • Hash mismatch errors: Usually means a dependency’s source has changed. Run nix flake update to refresh the lock file
  • Build runs out of disk: Set keep-derivations = false and keep-outputs = false in /etc/nix/nix.conf, then run nix store gc

Summary

  • Nix is a purely functional package manager providing reproducible, isolated package builds
  • It installs alongside existing package managers without conflicts — packages live in /nix/store
  • Flakes provide hermetic project definitions with lock files for team-wide reproducibility
  • nix develop creates instant development shells with precise dependency versions
  • 90,000+ packages are available, covering most development needs
  • The learning curve is steep but the reproducibility guarantees save significant debugging time
  • Use nix store gc regularly to manage disk usage