Flakes: Difference between revisions
You can't use channels like <nixpkgs> in a flake, remove erroneous advice |
refactor and organize layout; include sections on multiple architectures and devshells |
||
Line 121: | Line 121: | ||
<translate> | <translate> | ||
Flakes force you to specify a program for each supported architecture. To avoid this, | You will then be able to build this flake with <code>nix build</code> and run it with <code>nix run</code> | ||
{{note|Flakes force you to specify a program for each supported architecture. To avoid this, refer to [[#Defining a flake for multiple architectures]] section of the wiki.}} | |||
==== The nix flakes command ==== <!--T:64--> | |||
<!--T:65--> | |||
The {{ic|nix flake}} subcommand is described in {{Nix Manual|name=command reference page of the Nix manual|anchor=command-ref/new-cli/nix3-flake}}. | |||
This flake produces a single flake output <code>packagage</code>. And within that, <code>x86_64-linux</code> is a system-specifc attribute set. And within that, two package derivations <code>default</code> and <code>hello</code>. You can find outputs with the {{Nix Manual|name=show command|anchor=command-ref/new-cli/nix3-flake-show}} of a flake as shown below: | |||
<syntaxhighlight lang="console"> | |||
$ nix flake show | |||
└───packages | |||
└───x86_64-linux | |||
├───default: package 'hello-2.12.2' | |||
└───hello: package 'hello-2.12.2' | |||
</syntaxhighlight> | |||
==== Development shells ==== | |||
A <code>devShell</code> is a Nix-provided development environment defined within a flake. It lets you declare a reproducible shell environment with the tools, libraries, and environment variables you need for the development of a specific project. This is flake equivalent to defining a <code>nix-shell</code>. | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
description = "Example flake with a devShell"; | |||
inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; | |||
outputs = { self, nixpkgs}: | |||
let | |||
system = "x86_64-linux"; | |||
pkgs = import nixpkgs { inherit system; }; | |||
in { | |||
devShells.x86_64-linux.default = pkgs.mkShell { | |||
buildInputs = with pkgs; [ | |||
pkgs.hello | |||
]; | |||
shellHook = '' | |||
echo "Welcome to the devShell!" | |||
''; | |||
}; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
To enter the development shell environment: | |||
<syntaxhighlight lang="console"> | |||
$ nix develop | |||
</syntaxhighlight> | |||
{{note|You don’t need to define a devShell to enter a development shell using nix develop. | |||
If no devShell is defined, nix develop will drop you into an environment containing the default build dependencies of the flake (if any).}} | |||
==== Build specific attributes in a flake repository ==== <!--T:102--> | |||
<!--T:103--> | |||
Running <code>nix build</code> will look in the <code>legacyPackages</code> and <code>packages</code> output attributes for the corresponding derivation and then your system architecture and build the default output. If you want to specify a build attribute in a flake repository, you can run <code>nix build .#<attr></code>. In the example above, if you wanted to build the <code>packages.x86_64-linux.hello</code> attribute, run: | |||
<syntaxHighlight lang=console> | |||
$ nix build .#hello | |||
</syntaxHighlight> | |||
Likewise, you can specify an attribute with the run command: <code>nix run .#hello</code> and the develop command: <code>nix develop .#hello</code>. | |||
== Flake schema == <!--T:27--> | == Flake schema == <!--T:27--> | ||
Line 199: | Line 263: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<translate> | <translate> | ||
By default, Git submodules in package <code>src</code>'s won't get copied to the nix store, this may cause the build to fail. Flakes in Git repositories can declare that they need Git submodules to be enabled. Since Nix version [https://discourse.nixos.org/t/nix-2-27-0-released/62003 2.27], you can enable submodules by: | |||
<syntaxhighlight lang="nix"> | |||
inputs.self.submodules = true; | |||
</syntaxhighlight> | |||
=== Output schema === <!--T:42--> | === Output schema === <!--T:42--> | ||
Line 276: | Line 346: | ||
You can also define additional arbitrary attributes, but these are the outputs that Nix knows about. | You can also define additional arbitrary attributes, but these are the outputs that Nix knows about. | ||
==== | == Core usage patterns == | ||
=== Making your evaluations pure === <!--T:60--> | |||
<!--T:61--> | |||
Nix flakes are evaluated in a pure evaluation mode, meaning that access to the external environment is restricted to ensure reproducibility. To maintain purity when working with flakes, consider the following: | |||
<!--T:62--> | |||
* {{Nixpkgs Manual|name=fetchurl|anchor=#sec-pkgs-fetchers-fetchurl-inputs}} and {{Nixpkgs Manual|name=fetchzip|anchor=#sec-pkgs-fetchers-fetchzip-inputs}} require a <code>sha256</code> argument to be considered pure. | |||
<!--T:156--> | |||
* <code>builtins.currentSystem</code> is non-hermetic and impure as it reflects the host system performing the evauluation. This can usually be avoided by passing the system (i.e., x86_64-linux) explicitly to derivations requiring it. | |||
* <code>builtins.getEnv</code> is also impure. Avoid reading from environment variables and likewise, do not reference files outside of the flake's directory. | |||
== | === Defining a flake for multiple architectures === | ||
Flakes force you to specify a program for each supported architecture. An example below shows how to write a flake that targets multiple architectures. | |||
== | <syntaxhighlight lang="nix"> | ||
{ | |||
description = "A flake targeting multiple architectures"; | |||
inputs = { | |||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; | |||
}; | |||
== | outputs = { self, nixpkgs }: let | ||
systems = [ "x86_64-linux" "aarch64-linux" ]; | |||
forAllSystems = f: builtins.listToAttrs (map (system: { | |||
name = system; | |||
value = f system; | |||
}) systems); | |||
in { | |||
packages = forAllSystems (system: let | |||
pkgs = nixpkgs.legacyPackages.${system}; | |||
in { | |||
hello = pkgs.hello; | |||
default = pkgs.hello; | |||
}); | |||
}; | |||
} | |||
</syntaxhighlight> | |||
You can also use third-parties projects like [[Flake Utils|flake-utils]] or [[Flake Parts|flake-parts]] that automatically provide code to avoid this boilerplate. To avoid re-defining the program multiple times, refer to [[Flake Utils#Defining a flake for multiple architectures]] | |||
=== Using overlays === | |||
To use [[Overlays]] with flakes, refer to [[Overlays#In a Nix flake]] page. | |||
== | === Enable unfree software === <!--T:129--> | ||
< | To allow for [Unfree software|unfree software]] in a flake project, you need to explicitly allow it by setting <code>config.allowUnree = true;</code> when importing Nixpkgs. | ||
= | <syntaxhighlight lang="nix"> | ||
{ | |||
inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; | |||
outputs = { self, nixpkgs, flake-compat }: | |||
let | |||
system = "x86_64-linux"; | |||
pkgs = import nixpkgs { inherit system; config.allowUnfree = true;}; | |||
in { | |||
... | |||
}; | |||
} | |||
</syntaxhighlight> | |||
== NixOS configuration with flakes == | |||
== Using nix flakes with NixOS == <!--T:68--> | === Using nix flakes with NixOS === <!--T:68--> | ||
<!--T:69--> | <!--T:69--> | ||
Line 365: | Line 468: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<translate> | <translate> | ||
<!--T:73--> | <!--T:73--> | ||
<code>nixos-rebuild</code> also allows to specify different flake using the <code>--flake</code> flag | <code>nixos-rebuild</code> also allows to specify different flake using the <code>--flake</code> flag: | ||
</translate> | </translate> | ||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
# nixos-rebuild switch --flake . | |||
</syntaxhighlight> | </syntaxhighlight> | ||
<translate> | <translate> | ||
Line 381: | Line 483: | ||
</translate> | </translate> | ||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
# nixos-rebuild switch --flake /etc/nixos#joes-desktop | |||
</syntaxhighlight> | </syntaxhighlight> | ||
<translate> | <translate> | ||
Line 400: | Line 502: | ||
{{warning|Remote building seems to have an issue that's [https://github.com/NixOS/nixpkgs/issues/134952#issuecomment-1367056358 resolved by setting the <code>--fast</code> flag].}} | {{warning|Remote building seems to have an issue that's [https://github.com/NixOS/nixpkgs/issues/134952#issuecomment-1367056358 resolved by setting the <code>--fast</code> flag].}} | ||
= | === Importing packages from multiple nixpkgs branches === <!--T:110--> | ||
== Importing packages from multiple nixpkgs branches == <!--T:110--> | |||
<!--T:111--> | <!--T:111--> | ||
Line 608: | Line 566: | ||
<translate> | <translate> | ||
== Getting ''Instant'' System Flakes Repl == <!--T:116--> | === Pinning the registry on NixOS === <!--T:79--> | ||
</translate> | |||
<syntaxhighlight lang="nix"> | |||
{ inputs, ... }: | |||
{ | |||
nix.registry = { | |||
nixpkgs.flake = inputs.nixpkgs; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
<translate> | |||
<!--T:81--> | |||
To make sure the registry entry is "locked", use the following: | |||
</translate> | |||
<syntaxHighlight lang=nix> | |||
nix.registry = { | |||
nixpkgs.to = { | |||
type = "path"; | |||
path = pkgs.path; | |||
narHash = builtins.readFile | |||
(pkgs.runCommandLocal "get-nixpkgs-hash" | |||
{ nativeBuildInputs = [ pkgs.nix ]; } | |||
"nix-hash --type sha256 --sri ${pkgs.path} > $out"); | |||
}; | |||
}; | |||
</syntaxHighlight> | |||
<translate> | |||
<!--T:83--> | |||
This has the unfortunate side-effect of requiring import-from-derivation and slowing down build times, however it may greatly speed up almost every eval. Full-time flakes users may be able to just use <code>narHash = pkgs.narHash</code>. | |||
=== Getting ''Instant'' System Flakes Repl === <!--T:116--> | |||
<!--T:117--> | <!--T:117--> | ||
Line 683: | Line 675: | ||
<translate> | <translate> | ||
== | == Development tricks == <!--T:131--> | ||
=== Automatically switch nix shells with direnv === <!--T:97--> | |||
<!--T: | <!--T:98--> | ||
It is possible to automatically activate different Nix shells when navigating between project directories by using [[Direnv]]. Additional Nix integration with Direnv can be achieved with [https://github.com/nix-community/nix-direnv nix-direnv]. | |||
== | === Pushing Flakes to Cachix === <!--T:99--> | ||
</translate> | |||
https://docs.cachix.org/pushing#flakes | |||
<translate> | |||
=== Flake support in projects without flakes === <!--T:50--> | |||
<!--T:51--> | |||
The [https://github.com/edolstra/flake-compat flake-compat] library provides a compatibility layer that allows projects using traditional <code>default.nix</code> and <code>shell.nix</code> files to operate with flakes. For more details and usage examples, see the [[Flake Compat]] page. | |||
=== Accessing flakes from Nix expressions === <!--T:58--> | |||
<!--T:59--> | |||
If you want to access a flake from within a regular Nix expression on a system that has flakes enabled, you can use something like <code>(builtins.getFlake "/path/to/directory").packages.x86_64-linux.default</code>, where 'directory' is the directory that contains your <code>flake.nix</code>. | |||
=== Efficiently build multiple flake outputs === | |||
<!--T:101--> | |||
To push ''all'' flake outputs automatically, checkout [https://github.com/srid/devour-flake#usage devour-flake]. | |||
=== Build a package added in a PR === <!--T:161--> | === Build a package added in a PR === <!--T:161--> | ||
Line 759: | Line 772: | ||
== See also == <!--T:138--> | == See also == <!--T:138--> | ||
=== Official sources === | |||
<!--T:139--> | <!--T:139--> | ||
* [https://nix.dev/concepts/flakes Flakes] - nix.dev | * [https://nix.dev/concepts/flakes Flakes] - nix.dev | ||
<!--T:176--> | |||
* [https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html Nix flake command reference manual] - Many additional details about flakes, and their parts. | |||
<!--T:178--> | |||
* [https://github.com/NixOS/nix/blob/master/src/nix/flake.md spec describing flake inputs in more detail] | |||
<!--T:168--> | <!--T:168--> | ||
* [https://github.com/NixOS/rfcs/pull/49 RFC 49] (2019) - Original flakes specification | * [https://github.com/NixOS/rfcs/pull/49 RFC 49] (2019) - Original flakes specification | ||
=== Guides === | |||
<!--T:169--> | <!--T:169--> | ||
Line 786: | Line 809: | ||
<!--T:175--> | <!--T:175--> | ||
* [https://www.tweag.io/blog/2020-07-31-nixos-flakes/ Nix Flakes, Part 3: Managing NixOS systems] (Eelco Dolstra, 2020) | * [https://www.tweag.io/blog/2020-07-31-nixos-flakes/ Nix Flakes, Part 3: Managing NixOS systems] (Eelco Dolstra, 2020) | ||
<!--T:177--> | <!--T:177--> | ||
* [https://www.youtube.com/watch?v=QXUlhnhuRX4&list=PLgknCdxP89RcGPTjngfNR9WmBgvD_xW0l Nix flakes 101: Introduction to nix flakes] (Jörg Thalheim, 2020) | * [https://www.youtube.com/watch?v=QXUlhnhuRX4&list=PLgknCdxP89RcGPTjngfNR9WmBgvD_xW0l Nix flakes 101: Introduction to nix flakes] (Jörg Thalheim, 2020) YouTube video | ||
=== Useful flake modules === | |||
<!--T:179--> | <!--T:179--> | ||
* [ | * [[Flake Utils|flake-utils]]: Library to avoid some boiler-code when writing flakes | ||
* [[Flake Parts|flake-parts]]: Library to help write modular and organized flakes | |||
* [ | |||
<!--T:181--> | <!--T:181--> |