Flakes: Difference between revisions

Ardenet (talk | contribs)
No edit summary
Toastal (talk | contribs)
Add a tip to avoid putting everything into the flake.nix for compatibility
 
(18 intermediate revisions by 12 users not shown)
Line 5: Line 5:
<translate>
<translate>
<!--T:182-->
<!--T:182-->
'''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/development/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.


<!--T:183-->
<!--T:183-->
Line 11: Line 11:


<!--T:184-->
<!--T:184-->
Flakes also allow for locking references and versions, which can then be queried and updated programatically via the inputs {{cite manual|nix|command-ref/new-cli/nix3-flake-lock|number=7.5.19|title=nix flake lock}}{{cite manual|nix|command-ref/new-cli/nix3-flake-info|number=7.5.17|title=nix flake info}}. Additionally, an experimental CLI utility accepts flake references for expressions that build, run, and deploy packages.{{Cite manual|nix|command-ref/new-cli/nix|number=8.5.1|title=nix}}
Flakes also allow for locking references and versions, which can then be queried and updated programmatically via the inputs {{cite manual|nix|command-ref/new-cli/nix3-flake-lock|number=7.5.19|title=nix flake lock}}{{cite manual|nix|command-ref/new-cli/nix3-flake-info|number=7.5.17|title=nix flake info}}. Additionally, an experimental CLI utility accepts flake references for expressions that build, run, and deploy packages.{{Cite manual|nix|command-ref/new-cli/nix|number=8.5.1|title=nix}}


<!--T:185-->
== Flake file structure == <!--T:185-->
== 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:
<!--T:231-->
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 after [[#Setup]] using <code>nix flake init</code>. This will populate the current directory with a file called flake.nix that will contain something akin to:
</translate>
</translate>


Line 22: Line 22:
   description = "A very basic flake";
   description = "A very basic flake";


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


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}}


Line 38: Line 37:
<!--T:190-->
<!--T:190-->
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.
</translate>}}


<translate>
<!--T:232-->
<!--T:191-->
{{Note|Flakes require you to specify its outputs for each architecture separately. For more information, read the related section below.}}
=== Nix configuration ===
 
=== Nix configuration === <!--T:191-->


<!--T:233-->
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:
</translate>
</translate>
Line 61: Line 60:


<translate>
<translate>
<!--T:234-->
{{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>.}}
{{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>.}}


Line 81: Line 81:


<!--T:8-->
<!--T:8-->
Add the following to the [[Overview_of_the_NixOS_Linux_distribution#Declarative_Configuration system configuration |NixOS configuration]]:
Add the following to the [[NixOS system configuration#Usage|NixOS configuration]]:
</translate>
</translate>


Line 103: Line 103:


<!--T:14-->
<!--T:14-->
{{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.}}


<!--T:15-->
<!--T:15-->
Line 125: Line 125:
Therefore, if you use <code>git</code> for your flake, ensure to <code>git add</code> any project files after you first create them.}}
Therefore, if you use <code>git</code> for your flake, ensure to <code>git add</code> any project files after you first create them.}}


<!--T:64-->
=== The nix flakes command === <!--T:64-->
=== The nix flakes command ===
</translate>
</translate>


Line 136: Line 135:


<!--T:194-->
<!--T:194-->
This flake produces a single flake output <code>packages</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:
This flake produces a single flake output <code>packages</code>. And within that, <code>x86_64-linux</code> is a system-specific 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:
</translate>
</translate>


<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ nix flake show
$ nix flake show
path:/path/to/flake
└───packages
└───packages
     └───x86_64-linux
     └───x86_64-linux
         ├───default: package 'hello-2.12.2'
         ├───default: package 'hello-2.12.3'
         └───hello: package 'hello-2.12.2'
         └───hello: package 'hello-2.12.3'
</syntaxhighlight>
</syntaxhighlight>


Line 158: Line 158:
   description = "Example flake with a devShell";
   description = "Example flake with a devShell";


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 194: Line 194:


<!--T:103-->
<!--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:
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:
</translate>
</translate>


Line 223: Line 223:


<!--T:149-->
<!--T:149-->
* <code>nixConfig</code> is an attribute set of values which reflect the [https://nixos.org/manual/nix/stable/command-ref/conf-file.html values given to nix.conf]. This can extend the normal behavior of a user's nix experience by adding flake-specific configuration, such as a [[Binary Cache|binary cache]].
* <code>nixConfig</code> is an attribute set of values which reflect the [https://nix.dev/manual/nix/stable/command-ref/conf-file.html values given to nix.conf]. This can extend the normal behavior of a user's nix experience by adding flake-specific configuration, such as a [[Binary Cache|binary cache]].


=== Input schema === <!--T:31-->
=== Input schema === <!--T:31-->


<!--T:32-->
<!--T:32-->
[https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#flake-inputs The nix flake inputs manual].
[https://nix.dev/manual/nix/stable/command-ref/new-cli/nix3-flake.html#flake-inputs The nix flake inputs manual].


<!--T:150-->
<!--T:150-->
[https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#flake-references The nix flake references manual].
[https://nix.dev/manual/nix/stable/command-ref/new-cli/nix3-flake.html#flake-references The nix flake references manual].


<!--T:33-->
<!--T:33-->
Line 243: Line 243:


<translate>
<translate>
<!--T:235-->
Nixpkgs can alternatively also point to an url cached by the NixOS organization:
Nixpkgs can alternatively also point to an url cached by the NixOS organization:
</translate>
</translate>
Line 249: Line 250:


<translate>
<translate>
<!--T:236-->
In this example the input would point to the `nixpkgs-unstable` channel.
In this example the input would point to the `nixpkgs-unstable` channel.


Line 295: Line 297:


<!--T:151-->
<!--T:151-->
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/stable/command-ref/new-cli/nix3-flake-check.html#evaluation-checks nix flake check manual page].


<!--T:43-->
<!--T:43-->
Line 380: Line 382:


<!--T:156-->
<!--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.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.


<!--T:209-->
<!--T:209-->
Line 395: Line 397:
   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: {
      name = system;
        name = system;
      value = f system;
        value = f system;
    }) systems);
      }) systems);
  in {
    packages = forAllSystems (system: let
      pkgs = nixpkgs.legacyPackages.${system};
     in {
     in {
       hello = pkgs.hello;
       packages = forAllSystems (system: let
      default = pkgs.hello;
        pkgs = nixpkgs.legacyPackages.${system};
    });
      in {
  };
        hello = pkgs.hello;
        default = pkgs.hello;
      });
    };
}
}
</syntaxhighlight>
</syntaxhighlight>
Line 428: Line 430:


<!--T:218-->
<!--T:218-->
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.
To allow for [[Unfree software|unfree software]] in a flake project, you need to explicitly allow it by setting <code>config.allowUnfree = true;</code> when importing Nixpkgs.
</translate>
</translate>


Line 437: Line 439:
     let
     let
       system = "x86_64-linux";
       system = "x86_64-linux";
       pkgs = import nixpkgs { inherit system; config.allowUnfree = true;};
       pkgs = import nixpkgs { inherit system; config.allowUnfree = true; };
     in {
     in {
       ...
       ...
Line 467: Line 469:
<translate>
<translate>
=== Flake support in projects without flakes === <!--T:50-->
=== Flake support in projects without flakes === <!--T:50-->
{{Tip|Consider building your project in a manner where the <code>flake.nix</code> is merely <code>import</code>ing or <code>callPackage</code>ing stable Nix code to maximize compatibility for everyone as well as avoiding adding workaround dependencies to your project}}


<!--T:51-->
<!--T:51-->
Line 561: Line 565:


<!--T:176-->
<!--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.
* [https://nix.dev/manual/nix/stable/command-ref/new-cli/nix3-flake.html Nix flake command reference manual] - Many additional details about flakes, and their parts.


<!--T:178-->
<!--T:178-->