Nix and NixOS

Nix is a package manager and build system built on a simple, radical idea: treat building software like evaluating a pure function. Every package is built from exactly declared inputs — source code, dependencies, build scripts — and stored under a path containing a hash of those inputs, such as /nix/store/8m4…-postgresql-16.4. Different versions coexist without conflicts, upgrades are atomic, and rolling back is just switching to a previous set of paths. NixOS extends the same model to an entire Linux operating system: the whole machine — packages, services, users, kernel, firewall — is described in configuration files and built reproducibly.

Teams use Nix to give every developer and CI job the same toolchain, build hermetic artifacts and container images, and manage fleets of servers declaratively. The cost is a steep learning curve and a functional configuration language that feels unlike anything else in most toolchains.

TL;DR

Quick Example

A project development environment defined with a flake:

A NixOS server described declaratively and applied atomically:

Core Concepts

The Store and Derivations

A derivation is a precise description of a build: inputs, environment, and builder script. Nix builds derivations in sandboxes without network access (except for fixed-output downloads verified by hash), so undeclared dependencies cause failures rather than hidden coupling. Outputs land in /nix/store under input-addressed paths; the same inputs always map to the same path, which makes results cacheable and shareable.

The Nix Language and Nixpkgs

Nix expressions are written in a small, lazy, functional language. Nixpkgs is a huge collection of package definitions and NixOS modules, released in stable branches twice a year plus a rolling unstable branch. Overlays and overrides customize packages — applying patches or changing build options — without forking.

Flakes

Flakes standardize project structure: flake.nix declares inputs (such as a Nixpkgs revision) and outputs (packages, dev shells, NixOS configurations, checks), and flake.lock records exact input revisions. Flakes are still labeled experimental in upstream Nix but are widely used and enabled by default in some Nix distributions. They make "works on my machine" reproducible across machines.

Development Shells and Builds

Tools such as direnv load the dev shell automatically when you enter a directory.

Container Images

Nix can build OCI images from store paths (dockerTools.buildLayeredImage and similar), producing minimal images containing exactly the closure of the application's dependencies, with good layer reuse. See Docker.

Binary Caches

Because outputs are content-addressable, prebuilt results can be downloaded instead of rebuilt. The official cache covers Nixpkgs; services such as Cachix or self-hosted caches store your own builds, so CI builds once and developers download.

NixOS

NixOS builds the entire system — kernel, packages, configuration files, systemd services, users — from modules. nixos-rebuild switch builds a new system generation and activates it; previous generations remain bootable from the boot menu, making rollbacks trivial even after a bad kernel or configuration change. home-manager applies the same idea to user dotfiles and per-user packages, on NixOS or other operating systems. Fleet tools deploy NixOS configurations to many machines from one repository.

Nix in CI and Teams

Trade-Offs

Compare with containers for isolation, Ansible for configuring existing systems, and language package managers for application dependencies. See Infrastructure as Code and Package Managers.

Best Practices

Start With a Dev Shell

A flake.nix dev shell gives immediate value — consistent tools for everyone — with little Nix knowledge required.

Commit the Lock File

flake.lock is what makes builds reproducible; update it intentionally and review the changes.

Use a Binary Cache for Team Builds

Share build results across CI and developers so nobody rebuilds large dependencies.

Garbage Collect Regularly

Schedule store cleanup and limit retained generations so disks do not fill up.

Common Mistakes

Unpinned Channels

Imperative Changes on NixOS

Adopting Everything at Once

FAQ

What is Nix?

A package manager and build system that builds software from precisely declared inputs, stores results in an immutable store under hashed paths, and enables reproducible, side-by-side installations and atomic upgrades.

What is the difference between Nix and NixOS?

Nix is the package manager and build tool, usable on Linux and macOS. NixOS is a Linux distribution whose entire system configuration is managed declaratively with Nix.

What are Nix flakes?

A standard structure for Nix projects with declared inputs and outputs and a lock file pinning exact input versions, making builds and environments reproducible across machines.

Is Nix a replacement for Docker?

Not exactly. Nix manages packages and builds reproducibly; Docker packages and runs isolated containers. Nix can build minimal container images, and many teams use both.

Is Nix hard to learn?

It has a steep learning curve: a functional configuration language, new concepts like derivations and the store, and scattered documentation. Starting with development shells makes the first steps manageable.

Related Topics

References