Nix Flakes Why?¶
The difference between “Flakes” and “just Nix” (referring to the traditional, pre-flakes way of using Nix) is substantial, and it addresses some of the core challenges that made older Nix harder to use and less reliable. Here’s a detailed breakdown:
Reproducibility and Impurity¶
-
Traditional Nix (Impure by Default):
- Relied heavily on
NIX_PATH
, an environment variable that tells Nix where to find Nix expressions (likenixpkgs
). NIX_PATH
‘s variability (global, per-user, per-project) meant the same Nix expression could produce different results. This caused “it works on my machine” problems.- Nix expressions could “leak” dependencies from the system (files, environment variables), hindering truly isolated, reproducible builds.
- Channels (e.g.,
nixos-unstable
) managednixpkgs
versions, but were mutable. Channel updates could break builds.
- Relied heavily on
-
Flakes (Reproducible by Design):
- No
NIX_PATH
Dependence: Flakes use explicit, declarative inputs inflake.nix
, specifying exact dependency versions. flake.lock
: Pins inputs to specific versions (Git commits, tarball hashes), guaranteeing identical dependencies for all users.- Purity: Flakes are evaluated in a much more isolated environment, preventing accidental dependencies on external files or environment variables. This is crucial for reproducibility. Impurity is still possible (e.g., with
builtins.getEnv
), but is more explicit and avoidable. - No Channels (for Flakes): Replaces channels with direct Git repository references (or other sources) and their commits. This is more precise and avoids mutable channel problems.
- No
Project Structure and Discoverability¶
-
Traditional Nix:
- No standard project structure. Nix expressions could be scattered (
default.nix
,release.nix
, etc.), making project understanding difficult. - Discovering available packages/configurations was ad-hoc. You had to read the Nix expressions.
- No standard project structure. Nix expressions could be scattered (
-
Flakes:
flake.nix
Standard: Every flake has aflake.nix
at its root, describing inputs and outputs consistently.nix flake show
: Standard way to discover available outputs (packages, configurations, etc.) without reading Nix code.- Well-defined outputs: Flakes have conventional output attributes (
packages
,devShell
,nixosConfigurations
), clarifying what a flake provides.
Development Environments¶
-
Traditional Nix:
nix-shell
created development environments, often configured withshell.nix
. Butshell.nix
often had the same impurity problems as other Nix expressions.nix-shell
could be slow for large projects due to re-evaluations.
-
Flakes:
nix develop
: Uses thedevShell
output of a flake for reproducible development environments. The environment is defined inflake.nix
and locked byflake.lock
, ensuring consistency.nix develop
is generally faster thannix-shell
due to improved caching and evaluation.- Clean Separation: Development environment is a separate output, simplifying management and understanding.
NixOS Configuration¶
-
Traditional NixOS:
- System configurations typically lived in
/etc/nixos/configuration.nix
. This file could contain imperative code and be difficult to manage. - System updates (
nixos-rebuild switch
) could be risky, potentially breaking the system.
- System configurations typically lived in
-
Flakes with NixOS:
nixosConfigurations
Output: Flakes define entire NixOS system configurations as outputs, enabling declarative, reproducible system management.nixos-rebuild switch --flake .#my-config
: Build and switch to a specific configuration, ensuring you use the exact system version defined in the flake.- Atomic Updates: NixOS deployments with flakes are atomic. Either the entire new configuration is applied, or the system rolls back, significantly reducing the risk of a broken system.
Command-Line Interface¶
-
Traditional Nix:
nix-*
commands (nix-env
,nix-build
,nix-shell
) had an inconsistent and sometimes confusing interface. -
Flakes: The
nix
command (with experimental features enabled) provides a more unified and consistent CLI for working with flakes, designed for user-friendliness.
Caching¶
- Both: Both traditional Nix and Flakes use caching to speed up builds.
- Flakes (Improved Caching): Flakes generally have better caching due to more precise input tracking and evaluation. This leads to faster builds, especially for incremental changes. The lockfile facilitates sharing cached build results between machines.
Versioning and Updates¶
- Traditional Nix: Relied on updating channels, which could lead to unexpected breakages.
- Flakes:
nix flake update
explicitly updates the lock file, giving precise control over dependency versions.
In Summary: Key Advantages of Flakes¶
Flakes represent a significant improvement over traditional Nix, offering:
- True Reproducibility: Eliminates “works on my machine” problems.
- Declarative Management: Easier to understand and manage dependencies.
- Standardized Structure: Improves project organization and discoverability.
- Improved Development Workflows: Better way to create and manage dev environments.
- Safer NixOS Configuration: More reliable NixOS system management.
- Unified CLI: A more user-friendly command-line experience.
Flakes are highly recommended for new Nix projects and are increasingly adopted by existing projects due to these benefits.
Page last modified: 2025-02-27 16:35:42