Home |
There are plenty of benefits to using the Nix package manager, NixOS, and the rest of the Nix ecosystem. However, for people unfamiliar with Nix, one of the fundamental paradigm shifts is how Nix changes what it means to install a software package.
A traditional package manager will install software programs at the user’s whim
to a designated location on disk. These files are automatically exposed to your
environment via a PATH
or simply placed in a known location to be consumed.
/usr/bin/python3
This leads to three problems:
These problems are moot with the Nix architecture. This is because Nix doesn’t really have the concept of “installing” a program. Instead, packages are built (or downloaded from a cache) and placed in the Nix store, and packages are also exposed to the environment.
The Nix store is simply a location on your system (/nix/store/
) where
software that is built or downloaded by Nix resides. This is an immutable file
system that can only be altered by the Nix daemon. Every package sits in a
specific build directory with a unique name based on its package name and a
hash (such as pwvfrkynkyhbnidikifjz5skxq892g5a-ffmpeg-headless-6.1.1-lib/
).
These programs can all be accessed with the full Nix store path, but doing so would be incredibly tedious and impractical.
Every tool in the Nix ecosystem has a way of exposing packages from the Nix store to the current environment, such as NixOS, Home-Manager, Nix profiles, or Nix shells.
With these tools, you use the Nix language to declare the environment’s or
program’s dependencies, and Nix will automatically resolve them to the path in
the Nix store and use them as shared libraries or place them (or symlink them)
onto your current PATH
to be used like normal programs.
Here is the cool part: if you declare a program as a depencency for your environment, your system, or another program, Nix automatically build (or download) any dependencies that are missing from the Nix store.
This solves problem 1: you have a guarantee (after build time) that your environment includes the dependencies you have declared. What about problems 2 and 3?
For problem 2, Nix doesn’t worry about always keeping the exact set of packages built in the Nix store. Nix keeps track of which dependencies are required by your different environments, and when you choose to garbage collect it will simply purge the existing packages that are not declared as dependencies of anything else. You can set the garbage collector to run on a schedule; if you accidentally purge too aggressively, the worst case scenario is that you have to wait for Nix to rebuild or redownload a few packages.
For problem 3, the uniqueness of the Nix store paths allow you to reference multiple packages with the same name. You can expose one version of a package to one project shell environment and another version to a specific dependant package, while another lives in your default shell. If they all happen to require the exact same version, then great — you get to save some space. But otherwise, you don’t ever have to think about it.
The Nix ecosystem has a ton of benefits: declarative configuration, build guarantees, Nixpkgs availability, rollbacks, lazy functional modules, temporary environments, but fundamentally they all are sourced from rethinking, from the ground up, what software installation means.