Flakes/en: Difference between revisions

FuzzyBot (talk | contribs)
Updating to match new version of source page
Tags: Mobile edit Mobile web edit
FuzzyBot (talk | contribs)
Updating to match new version of source page
 
(3 intermediate revisions by the same user not shown)
Line 3: Line 3:
{{Cleanup}}
{{Cleanup}}


'''Nix flakes''' are an [[Experimental Nix features|experimental feature]] first introduced in the 2.4 [[Nix]] release,{{Cite manual|nix|development/experimental-features|number=13.8|title=Experimental Features|subsection=xp-feature-flakes|subtitle=flakes}}{{Cite manual|nix|release-notes/rl-2.4|number=14.27|title=Release 2.4 (2021-11-01)}} aiming to address a number of areas of improvement for the Nix ecosystem: they provide a uniform structure for Nix projects, allow for pinning specific versions of each dependencies, and sharing these dependencies via lock files, and overall make it more convenient to write reproducible Nix expressions.
'''Nix flakes''' are an [https://nix.dev/manual/nix/stable/contributing/experimental-features experimental feature] first introduced in the 2.4 [[Nix]] release,{{Cite manual|nix|development/experimental-features|number=13.8|title=Experimental Features|subsection=xp-feature-flakes|subtitle=flakes}}{{Cite manual|nix|release-notes/rl-2.4|number=14.27|title=Release 2.4 (2021-11-01)}} aiming to address a number of areas of improvement for the Nix ecosystem: they provide a uniform structure for Nix projects, allow for pinning specific versions of each dependencies, and sharing these dependencies via lock files, and overall make it more convenient to write reproducible Nix expressions.


A flake is a directory which directly contains a Nix file called <code>flake.nix</code>, that follows a very specific structure. Flakes introduce a URL-like syntax{{Cite manual|nix|command-ref/new-cli/nix3-flake|number=8.5.17|title=nix flake|subsection=url-like-syntax|subtitle=URL-like syntax}} for specifying remote resources. To simplify the URL syntax, flakes use a registry of symbolic identifiers,{{Cite manual|nix|command-ref/new-cli/nix3-registry|number=8.5.62|title=nix registry}} allowing the direct specification of resources through syntax such as <code>github:NixOS/nixpkgs</code>.
A flake is a directory which directly contains a Nix file called <code>flake.nix</code>, that follows a very specific structure. Flakes introduce a URL-like syntax{{Cite manual|nix|command-ref/new-cli/nix3-flake|number=8.5.17|title=nix flake|subsection=url-like-syntax|subtitle=URL-like syntax}} for specifying remote resources. To simplify the URL syntax, flakes use a registry of symbolic identifiers,{{Cite manual|nix|command-ref/new-cli/nix3-registry|number=8.5.62|title=nix registry}} allowing the direct specification of resources through syntax such as <code>github:NixOS/nixpkgs</code>.
Line 10: Line 10:


== Flake file structure ==
== Flake file structure ==
Minimally, a flake file contains a description of the flake, a set of input dependencies and an output. You can generate a very basic flake file at any time using nix flake init. This will populate the current directory with a file called flake.nix that will contain something akin to:
Minimally, a flake file contains a description of the flake, a set of input dependencies and an output. You can generate a very basic flake file at any time using nix flake init. This will populate the current directory with a file called flake.nix that will contain something akin to:
{{File|3=<nowiki>{
{{File|3=<nowiki>{
   description = "A very basic flake";
   description = "A very basic flake";
Line 19: Line 21:


   outputs = { self, nixpkgs }: {
   outputs = { self, nixpkgs }: {
 
     packages.x86_64-linux = {
     packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;
      default = self.packages.x86_64-linux.hello;
 
      hello = nixpkgs.legacyPackages.x86_64-linux.hello;
    packages.x86_64-linux.default = self.packages.x86_64-linux.hello;
    };
 
   };
   };
}</nowiki>|name=flake.nix|lang=nix}}
}</nowiki>|name=flake.nix|lang=nix}}
In the example above, you can see the description, the input specified as a GitHub repository with a specific branch (here <code>nixos/nixpkgs</code> on the <code>nixos-unstable</code> branch), and an output that makes use of the input. The output simply specifies that the flake contains one package for the x86_64 architecture called <code>hello</code>. Even if your flake's output wouldn't use its input (however, in practice, that is highly unlikely), the output still needs to be a Nix function.
In the example above, you can see the description, the input specified as a GitHub repository with a specific branch (here <code>nixos/nixpkgs</code> on the <code>nixos-unstable</code> branch), and an output that makes use of the input. The output simply specifies that the flake contains one package for the x86_64 architecture called <code>hello</code>. Even if your flake's output wouldn't use its input (however, in practice, that is highly unlikely), the output still needs to be a Nix function.
{{Note|Flakes require you to specify its outputs for each architecture separately. For more information, read the related section below.}}
{{Note|Flakes require you to specify its outputs for each architecture separately. For more information, read the related section below.}}


=== Nix configuration ===
=== Nix configuration ===
It is possible to override the global Nix configuration set in your <code>nix.conf</code> file for the purposes of evaluating a flake. This can be useful, for example, for setting up binary caches specific to certain projects, while keeping the global configuration untouched. The flake file can contain a nixConfig attribute with any relevant configuration settings supplied. For example, enabling the nix-community binary cache would be achieved by:
It is possible to override the global Nix configuration set in your <code>nix.conf</code> file for the purposes of evaluating a flake. This can be useful, for example, for setting up binary caches specific to certain projects, while keeping the global configuration untouched. The flake file can contain a nixConfig attribute with any relevant configuration settings supplied. For example, enabling the nix-community binary cache would be achieved by:
{{File|3=<nowiki>{
{{File|3=<nowiki>{
   ...
   ...
Line 41: Line 46:
     ];
     ];
   }
   }
}</nowiki>|name=flake.nix|lang=nix}}{{Note|If you are used to configuring your Nix settings via the NixOS configuration, these options are under <code>nix.settings</code> and not <code>nix</code>. For example, you cannot specify the automatic storage optimisation under <code>nix.optimisation.enable</code>.}}
}</nowiki>|name=flake.nix|lang=nix}}
 
{{Note|If you are used to configuring your Nix settings via the NixOS configuration, these options are under <code>nix.settings</code> and not <code>nix</code>. For example, you cannot specify the automatic storage optimisation under <code>nix.optimisation.enable</code>.}}


== Setup ==
== Setup ==
Line 48: Line 55:


When using any [[Nix command|<code>nix</code> command]], add the following command-line options:
When using any [[Nix command|<code>nix</code> command]], add the following command-line options:
<syntaxhighlight lang="shell">
<syntaxhighlight lang="shell">
  --experimental-features 'nix-command flakes'
  --experimental-features 'nix-command flakes'
</syntaxhighlight>
</syntaxhighlight>
=== Enabling flakes permanently ===
=== Enabling flakes permanently ===


Line 71: Line 80:
====Nix standalone====
====Nix standalone====


{{Note | The  [https://github.com/DeterminateSystems/nix-installer Determinate Nix Installer] enables flakes by default.}}
{{Note | The  [https://github.com/DeterminateSystems/nix-installer Determinate Nix Installer] enables flakes by default, but installs the proprietary Determinate Nix.}}


Add the following to <code>~/.config/nix/nix.conf</code> or <code>/etc/nix/nix.conf</code>:
Add the following to <code>~/.config/nix/nix.conf</code> or <code>/etc/nix/nix.conf</code>:
Line 78: Line 87:
experimental-features = nix-command flakes
experimental-features = nix-command flakes
</syntaxHighlight>
</syntaxHighlight>
== Usage ==
== Usage ==


Line 87: Line 97:


=== The nix flakes command ===
=== The nix flakes command ===
{{Main|Nix (command)}}
{{Main|Nix (command)}}


Line 111: Line 122:
   inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
   inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";


   outputs = { self, nixpkgs}:
   outputs = { self, nixpkgs }:
     let
     let
       system = "x86_64-linux";
       system = "x86_64-linux";
Line 139: Line 150:
==== Build specific attributes in a flake repository ====
==== Build specific attributes in a flake repository ====


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:
Running <code>nix build</code> will look in the <code>legacyPackages</code> and <code>packages</code> output attributes for the corresponding [[derivations|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>
<syntaxHighlight lang=console>
Line 178: Line 189:


In this example the input would point to the `nixpkgs-unstable` channel.
In this example the input would point to the `nixpkgs-unstable` channel.


For any repository with its own flake.nix file, the website must also be defined. Nix knows where the nixpkgs repository is, so stating that it's on GitHub is unnecessary.
For any repository with its own flake.nix file, the website must also be defined. Nix knows where the nixpkgs repository is, so stating that it's on GitHub is unnecessary.
Line 210: Line 220:
=== Output schema ===
=== Output schema ===


This is described in the nix package manager [https://github.com/NixOS/nix/blob/master/src/nix/flake-check.md src/nix/flake-check.md].
The output schema is described the [https://nix.dev/manual/nix/2.33/command-ref/new-cli/nix3-flake-check.html#evaluation-checks nix flake check manual page].


Once the inputs are resolved, they're passed to the function `outputs` along with with `self`, which is the directory of this flake in the store. `outputs` returns the outputs of the flake, according to the following schema.
Once the inputs are resolved, they're passed to the function `outputs` along with with `self`, which is the directory of this flake in the store. `outputs` returns the outputs of the flake, according to the following schema.
Line 224: Line 234:
* <code><store-path></code> is a <code>/nix/store..</code> path
* <code><store-path></code> is a <code>/nix/store..</code> path


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{ self, ... }@inputs:
{ self, ... }@inputs:
{
{
Line 237: Line 247:
     type = "app";
     type = "app";
     program = "<store-path>";
     program = "<store-path>";
    meta = {description = "..."; inherit otherMetaAttrs; };
   };
   };
   # Executed by `nix run . -- <args?>`
   # Executed by `nix run . -- <args?>`
   apps."<system>".default = { type = "app"; program = "..."; };
   apps."<system>".default = { type = "app"; program = "..."; meta = {description = "..."; inherit otherMetaAttrs; }; };


   # Formatter (alejandra, nixfmt or nixpkgs-fmt)
   # Formatter (alejandra, nixfmt, treefmt-nix or nixpkgs-fmt)
   formatter."<system>" = derivation;
   formatter."<system>" = derivation;
   # Used for nixpkgs packages, also accessible via `nix build .#<name>`
   # Used for nixpkgs packages, also accessible via `nix build .#<name>`
Line 270: Line 281:
   templates.default = { path = "<store-path>"; description = ""; };
   templates.default = { path = "<store-path>"; description = ""; };
}
}
</syntaxHighlight>
</syntaxhighlight>


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.
Line 282: Line 293:
* {{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.
* {{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.


* <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.currentSystem</code> is non-hermetic and impure as it reflects the host system performing the evaluation. 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.
*  <code>builtins.getEnv</code> is also impure. Avoid reading from environment variables and likewise, do not reference files outside of the flake's directory.
Line 294: Line 305:
   description = "A flake targeting multiple architectures";
   description = "A flake targeting multiple architectures";


  inputs = {
inputs = {
     nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
     nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
   };
   };


  outputs = { self, nixpkgs }: let
outputs = { self, nixpkgs }: let
     systems = [ "x86_64-linux" "aarch64-linux" ];
     systems = [ "x86_64-linux" "aarch64-linux" ];
     forAllSystems = f: builtins.listToAttrs (map (system: {
     forAllSystems = f: builtins.listToAttrs (map (system: {
Line 415: Line 426:
# Output should show ~/libdep-src-checkout/ so you know it worked
# Output should show ~/libdep-src-checkout/ so you know it worked
</syntaxHighlight>
</syntaxHighlight>


If Nix warns you that your redirected flake isn't actually used as an input to the evaluated flake, try using the <code>--inputs-from .</code> flag. If all worked well you should be able to <code>buildPhase && installPhase</code> when the dependency changes and rebuild your consumer with the new version ''without'' exiting the development shell.
If Nix warns you that your redirected flake isn't actually used as an input to the evaluated flake, try using the <code>--inputs-from .</code> flag. If all worked well you should be able to <code>buildPhase && installPhase</code> when the dependency changes and rebuild your consumer with the new version ''without'' exiting the development shell.
Line 460: Line 472:
{{references}}
{{references}}


[[Category:Software]]
[[Category:Software|Software]]
[[Category:Nix]]
[[Category:Nix|Nix]]
[[Category:Nix Language]]
[[Category:Nix Language|Nix Language]]
[[Category:Flakes]]
[[Category:Flakes|Flakes]]