How NixOS Uses a Purely Functional Package Manager
NixOS redefines Linux system administration by using the Nix package manager to treat the operating system as the output of a pure function. Instead of mutating files in standard directories, NixOS builds system components in isolated environments and manages them declaratively through a single configuration file. This approach eliminates dependency conflicts, allows reproducible system builds, and provides atomic upgrades alongside instant rollbacks.
The Foundation: Pure Functions and Immutability
In computer science, a pure function always produces the exact same output given the same inputs and causes no side effects. The Nix package manager applies this principle to software deployment. A package build recipe—written in the Nix expression language—declares every dependency, source file, compiler flag, and configuration option as an explicit input.
When Nix builds software, it performs the compilation in an isolated
chroot environment with no network access and no access to undeclared
system libraries. The resulting binaries are stored in the
/nix/store directory using a unique cryptographic hash
derived from all build inputs (for example,
/nix/store/b685...-nginx-1.24.0/). Because the path depends
on the exact inputs, packages are completely immutable. Once written to
the store, they are never modified in place.
The Global Store and Symlink Trees
Traditional Linux distributions place binaries in /bin,
/usr/bin, and libraries in /lib, creating a
shared, mutable environment where package updates can overwrite
dependencies required by other software. NixOS eliminates standard file
hierarchy mutations.
Every application, configuration file, and kernel module exists in
its own isolated directory inside /nix/store. NixOS
constructs the running system state by assembling a tree of symbolic
links pointing back to these store paths. A binary that requires a
specific version of OpenSSL links directly to that version's unique path
in /nix/store, allowing multiple conflicting versions of
the same library to coexist seamlessly on the same machine.
Declarative System Configuration
NixOS extends the functional paradigm from isolated applications to
the entire operating system. The user describes the target state of the
entire system inside a centralized configuration file, typically
configuration.nix.
This file declares:
- Installed packages and system utilities
- System services and their runtime configurations
- User accounts and security privileges
- Kernel modules, file systems, and bootloader settings
When the administrator applies changes using the command
nixos-rebuild switch, Nix evaluates the configuration,
builds or downloads the necessary store paths, creates a new system
closure, and updates symlinks to make the new configuration active.
Atomic Upgrades and Generations
Because changes in NixOS do not overwrite existing files, upgrades
are atomic. A new system generation is fully assembled in
/nix/store before the system switches to it. If the build
or download process fails halfway through, the currently running system
remains untouched and functional.
Each successful rebuild produces a new system "generation." NixOS
preserves previous generations until the administrator explicitly runs a
garbage collection command. If an update introduces an unstable kernel
or broken package, the administrator can roll back to the previous
generation instantly by running nixos-rebuild --rollback or
by selecting an earlier generation directly from the GRUB or
systemd-boot menu at startup.
Absolute Reproducibility
By combining pure evaluations with locked dependency inputs, NixOS achieves environmental reproducibility. An entire workstation or server fleet can be cloned to an identical state across different hardware targets simply by sharing the configuration code. By tracking dependencies mathematically rather than imperatively, NixOS provides a resilient, predictable Linux platform.