Flakes#
What are flakes?#
Flakes offer an entrypoint file flake.nix aimed at sharing Nix code.
They make it easy to build programs with the same version.
flake.nix is a file that declares inputs and outputs with a standard structure.
Note: Experimental, requires Nix 2.4.
This file can look like:
1{
2 description = "My example flake";
3
4 inputs = {
5 nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
6 };
7
8 outputs = { self, nixpkgs }: {
9 packages.x86_64-linux = {
10 default = self.packages.x86_64-linux.hello;
11 hello = nixpkgs.legacyPackages.x86_64-linux.hello;
12 };
13 };
14}
outputs include various built-in types, but can be extended.
You can find an overview of these on the wiki.
inputs let you declare dependencies.
Nix creates a flake.lock to pin dependencies once you run a nix command.
If these dependencies have inputs of their own, Nix will check their lock files to find the versions to use.
Using the same versions helps make sure programs work as intended, but you can override these.
nix commands natively integrate with flakes by default.
nix build github:NixOS/nixpkgs#hello
You may pass references to local (e.g. .) or remote (e.g. github:NixOS/nixpkgs) project directories.
For further details see the reference on nix commands.
Aliases to flakes are stored in a registry.
This can be extended by command-line or by NixOS option nix.registry.
The NixOS manual further explains flake-based installs.
Should I use flakes in my project?#
Flakes are an experimental extension format with outstanding issues. Its functionality can generally be achieved without them as well.
If you need to run existing software that already used flakes, or want to contribute to their development, feel free to use them. If you want to write Nix code yourself, consider also our guide on dependency management.[1] This overview can help get what you need from flakes while preserving compatibility.
Discoverability#
A first step in use of flakes is to add a flake.nix file specifying outputs.
Pros:
Use the code from other flake projects.
Nix checks
flake.nix’s structure is valid.
Cons:
Flakes have no parameters. This means
flake.nixand its end-user must be explicit about the usedsystem. This is made easier by sayflake-utils.As an experimental feature, flakes can still change.
Alternatives:
Use flakes as thin wrappers over existing Nix code. This way, code can be used in both ways.
Use Nix modules: flake users can import these with
flake = false;.
Running commands#
Flakes are used from Nix’s v3 nix command line interface.
It can build or run programs by a reference like . or github:NixOS/nixpkgs.
You can enable this for one command by adding:
--experimental-features 'nix-command flakes'
Or permanently in NixOS or Home Manager configurations using:
nix.settings.experimental-features = [ "nix-command" "flakes" ];
To build the derivation in your flake.nix’s packages.x86_64-linux.default, run:
nix build .#packages.x86_64-linux.default
You can shorten this to nix build .#default, or just nix build.
nix run runs programs in outputs.apps.
nix run .#default runs outputs.apps.default.
Just nix run also runs that.
For example, to run the hello package from Nixpkgs:
nix run nixpkgs#hello -- --greeting "hello from flakes"
This uses the version set by your registry’s alias nixpkgs.
To run the hello package from Nixpkgs’ nixpkgs-unstable branch:
nix run github:NixOS/nixpkgs/nixpkgs-unstable#hello
Pros:
Flakes cache builds to save time on later identical builds. This can save time if you run unchanged builds in Continuous Integration, for example.
Flakes promote making programs easy to run, also from remote repositories.
Flakes default to running in pure mode. This promotes a style of writing programs more likely to make them reproducible[2].
Flakes build only tracked files, for projects using Git. This helps prevent rebuilds.
Cons:
Builds copy the whole flake directory to the Nix store. This caches them, but can be slower for large repositories like Nixpkgs.
The implementation still has issues for both flakes and the v3 CLI.
Files must be staged for flakes to see them.
Alternatives:
Plain Nix files can be used with the [v2 commands] (like
nix-build,nix-shell), or with v3 commands’--fileflag or-f.In NixOS, you can make v3 commands’
nixpkgsto a package setpkgsby settingnixpkgs.flake.source = pkgs.path;in your NixOS configuration. Also see managing dependencies.Using
builtins.fetchTreefrom experimental featurefetch-tree,nix runmay be emulated[3] for non-flake entrypoints.
Dependency management#
Flakes’ inputs attribute can manage dependencies.
By default this handles recursive dependencies implicitly.
In case a library is used multiple times, this can give different versions of the same library.
You can override these if you want using follows statements:
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
};
}
This way, Home Manager’s inputs reuse your chosen nixpkgs.
If you don’t want to load a dependency, you can also disable it.
In the above example, that could look like inputs.home-manager.inputs.nixpkgs = null;.
Pros:
Make it easy to reproduce published software, following the versions they used.
You can override recursive inputs.
Cons:
Flakes by default follow versions from dependencies’
flake.lock, so if you don’t override these withfollows, you may get:multiple versions of the same dependency.
outdated dependencies, if their versions are not actively updated.
Dependencies are fetched eagerly, loading dependencies you may not use.
Dependencies managed by flake inputs are hard to override if you don’t also use flakes.
If your flake is used as a library, you need to add
followsstatements for all recursive inputs. Otherwise downstream consumers cannot add theirfollowson your indirect inputs.
Alternatives:
Handle dependencies with
npins.Handle dependencies inline using functions such as the fetchers or
builtins.fetchTree.
Flake-only Nix#
As flakes (largely[4]) use Nix as an internal language, you could even place all Nix code in flake files.
In the community, such a coding style is called dendritic pattern.
Using flakes, this pattern gets easier with library flake-parts,
which lets you spread code over different flake-like files.
Pros:
Helps use flakes’ schema and inputs from any such Nix code.
Cons:
Makes it harder to access this code without using flakes.
Alternatives:
Use flakes as thin wrappers over existing Nix code, so code can be used in both ways.
Use library
flake-compatto expose a flake’s default package or shell to non-flake users.Propagate needed parameters across modules explicitly or with NixOS’s
specialArgs.
History#
Conception
Design
The flakes proposal was criticised for trying to solve too many problems at once and at the wrong abstraction layer.
The design still has various problems including around versioning, composability, cross-compilation, and tight coupling with nixpkgs.
There are also still many open design questions around the
nixCLI.
Implementation
There are still problems with the implementation.
Process
While there were still outstanding concerns about the design, the implementation was merged without the RFC having been accepted (and in fact being withdrawn on merge), raising questions about proper process.
The RFC was closed with no timeline to conclude the experiment.
Flakes had become depended on by many projects, making it harder to iterate on their design without breaking many people’s code.
Community
The design had not been accepted by all parts of the community, with e.g. Nixpkgs not using it in its internal tooling. As a result of this, branching approaches to flakes have been made, with e.g. company Determinate Systems (which offers proprietary features around flakes) unilaterally declaring the feature stable, while community-driven Nix fork Lix consolidated the featureset to a de-facto ‘v1’. Such branching could potentially end up breaking the promise of a unified interface that propelled the flakes experiment in the first place.
Further reading#
Flakes aren’t real and cannot hurt you: a guide to using Nix flakes the non-flake way (Jade Lovelace, January 2024)
Nix Flakes is an experiment that did too much at once… (comments) (Samuel Dionne-Riel, September 2023)
Experimental does not mean unstable (comments) (Graham Christensen, September 2023)
The Nix Hour: comparing flakes to traditional Nix (Silvan Mosberger, November 2022)