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
- Packages live in the immutable Nix store, under paths that hash all their inputs.
- Derivations describe how to build something; Nixpkgs provides over 100,000 packages.
- Flakes (
flake.nixplusflake.lock) pin inputs exactly for reproducible projects. nix developgives every developer and CI job the same toolchain without polluting the system.- NixOS builds the whole operating system from configuration; every change creates a generation you can roll back to.
- Binary caches avoid rebuilding; the main trade-offs are learning curve, documentation gaps, and disk usage.
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
- Reproducible CI: run every job inside
nix developornix build, so CI uses exactly the developer toolchain. - Caching: push build outputs to a binary cache to keep CI fast.
- Incremental adoption: start with a dev shell for one repository before packaging builds or managing machines.
- Pin and update deliberately: review
flake.lockupdates like dependency upgrades.
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
- DevOps — Delivery practices and tooling
- Package Managers — How software is installed and versioned
- Docker — Containers and images
- Infrastructure as Code — Declarative infrastructure
- CI/CD — Reproducible pipelines
- Linux — The platform NixOS builds on