Flakes: Difference between revisions

Pigs (talk | contribs)
You can't use channels like <nixpkgs> in a flake, remove erroneous advice
Pigs (talk | contribs)
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, third-parties projects like [[Flake Utils|flake-utils]] or [[Flake Parts|flake-parts]] 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]]
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.


==== nix run ==== <!--T:49-->
== 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.


<!--T:155-->
<code>builtins.getEnv</code> is also impure. Avoid reading from environment variables and likewise, do not reference files outside of the flake's directory.
When output <code>apps.<system>.myapp</code> is not defined, <code>nix run myapp</code> runs <code><packages or legacyPackages.<system>.myapp>/bin/<myapp.meta.mainProgram or myapp.pname or myapp.name (the non-version part)></code>


== Flake support in projects without flakes == <!--T:50-->
=== Defining a flake for multiple architectures ===


<!--T:51-->
Flakes force you to specify a program for each supported architecture. An example below shows how to write a flake that targets multiple architectures.
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-->
<syntaxhighlight lang="nix">
{
  description = "A flake targeting multiple architectures";


<!--T:59-->
  inputs = {
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>.
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
  };


== Making your evaluations pure == <!--T:60-->
  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>


<!--T:61-->
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]]
Nix flakes run in pure evaluation mode, which is underdocumented. Some tips for now:


<!--T:62-->
=== Using overlays ===
* fetchurl and fetchtar [https://github.com/NixOS/nix/blob/36c4d6f59247826dde32ad2e6b5a9471a9a1c911/src/libexpr/primops/fetchTree.cc#L201 require] a sha256 argument to be considered pure.


<!--T:156-->
To use [[Overlays]] with flakes, refer to [[Overlays#In a Nix flake]] page.
* builtins.currentSystem is non-hermetic and impure. This can usually be avoided by passing the system (i.e., x86_64-linux) explicitly to derivations requiring it.


== The nix flakes command == <!--T:64-->
=== Enable unfree software === <!--T:129-->


<!--T:65-->
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.
The {{ic|nix flake}} subcommand is described in [https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html command reference page of the unstable manual].


== Install packages with `nix profile` == <!--T:66-->
<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>  


<!--T:67-->
== NixOS configuration with flakes ==
[https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-profile-install.html <code>nix profile install</code> in the manual]


== 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 (# is optional):
<code>nixos-rebuild</code> also allows to specify different flake using the <code>--flake</code> flag:


</translate>
</translate>
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ sudo nixos-rebuild switch --flake .
# nixos-rebuild switch --flake .
</syntaxhighlight>
</syntaxhighlight>
<translate>
<translate>
Line 381: Line 483:
</translate>
</translate>
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ sudo nixos-rebuild switch --flake /etc/nixos#joes-desktop
# 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].}}


== Pinning the registry on NixOS == <!--T:79-->
=== Importing packages from multiple nixpkgs branches === <!--T:110-->
 
</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>.
 
== Super fast nix-shell == <!--T:84-->
 
<!--T:85-->
A feature of the nix Flake edition is that Nix evaluations are cached.
 
<!--T:86-->
Let’s say that your project has a <code>shell.nix</code> file that looks like this:
 
</translate>
<syntaxhighlight lang="nix">
{
  pkgs ? import <nixpkgs> { },
}:
pkgs.mkShell {
  packages = [ pkgs.nixfmt ];
 
  shellHook = ''
    # ...
  '';
}
</syntaxhighlight>
<translate>
 
<!--T:89-->
Running nix-shell can be a bit slow and take 1-3 seconds.
 
<!--T:90-->
Now create a <code>flake.nix</code> file in the same repository:
 
</translate>
<syntaxhighlight lang="nix">
{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
 
  outputs =
    { nixpkgs, ... }:
    {
      /*
        This example assumes your system is x86_64-linux
        change as neccesary
      */
      devShells.x86_64-linux =
        let
          pkgs = nixpkgs.legacyPackages.x86_64-linux;
        in
        {
          default = pkgs.mkShell {
            packages = [ pkgs.hello ];
          };
        };
    };
}
}
</syntaxhighlight>
<translate>
 
<!--T:93-->
( If you're in a git repository run `git add flake.nix` so that Nix recognizes it. )
 
<!--T:94-->
And finally, run <code>nix develop</code>. This is what replaces the old nix-shell invocation.
 
<!--T:95-->
Exit and run again, this command should now be super fast.
 
<!--T:96-->
{{warning|TODO: there is an alternative version where the defaultPackage is a pkgs.buildEnv that contains all the dependencies. And then nix shell is used to open the environment.}}
 
== Automatically switch nix shells with direnv == <!--T:97-->
 
<!--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>
 
<!--T:101-->
To push ''all'' flake outputs automatically, checkout [https://github.com/srid/devour-flake#usage devour-flake].
 
== Build specific attributes in a flake repository == <!--T:102-->
 
<!--T:103-->
When in the repository top-level, run <code>nix build .#<attr></code>. It will look in the <code>legacyPackages</code> and <code>packages</code> output attributes for the corresponding derivation.
 
<!--T:104-->
Eg, in nixpkgs:
 
</translate>
<syntaxHighlight lang=console>
$ nix build .#hello
</syntaxHighlight>
<translate>
 
=== Building flakes from a Git repo url with submodules === <!--T:106-->
 
<!--T:107-->
As per nix 2.9.1, git submodules in package <code>src</code>'s won't get copied to the nix store, this may cause the build to fail.  To workaround this, use:
 
</translate>
<syntaxhighlight lang="console">
nix build '.?submodules=1#hello'
</syntaxhighlight>
<translate>
 
<!--T:109-->
See: https://github.com/NixOS/nix/pull/5434
 
== 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>


== Enable unfree software == <!--T:129-->
== Development tricks == <!--T:131-->
 
=== Automatically switch nix shells with direnv === <!--T:97-->


<!--T:130-->
<!--T:98-->
Refer to [[Unfree software|Unfree Software]].
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].


== Development tricks == <!--T:131-->
=== 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: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: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


<!--T:178-->
=== Useful flake modules ===
* [https://github.com/NixOS/nix/blob/master/src/nix/flake.md spec describing flake inputs in more detail]


<!--T:179-->
<!--T:179-->
* [https://github.com/numtide/flake-utils flake-utils: Library to avoid some boiler-code when writing flakes]
* [[Flake Utils|flake-utils]]: Library to avoid some boiler-code when writing flakes


<!--T:180-->
* [[Flake Parts|flake-parts]]: Library to help write modular and organized flakes
* [https://zimbatm.com/NixFlakes/#direnv-integration zimbat's direnv article]


<!--T:181-->
<!--T:181-->