Flakes: Difference between revisions

remove untrue or unqualified statements
Tags: Mobile edit Mobile web edit
Gerg-L (talk | contribs)
Fix flake refs, remove system from lib.nixosSystem remove flake-utils, clarify some examples
Line 31: Line 31:
Add the following to your home-manager config:
Add the following to your home-manager config:


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
   nix = {
   nix.settings.experimental-features = [ "nix-command" "flakes" ];
    package = pkgs.nix;
</syntaxhighlight>
    settings.experimental-features = [ "nix-command" "flakes" ];
  };
</syntaxHighlight>


=====Other Distros, without Home-Manager=====
=====Other Distros, without Home-Manager=====
Line 91: Line 88:
Nixpkgs can be defined using the following code:
Nixpkgs can be defined using the following code:


<code>inputs.nixpkgs.url = "nixpkgs/<branch name>";</code>
<code>inputs.nixpkgs.url = "github:NixOS/nixpkgs/<branch name>";</code>


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 105: Line 102:
Using curly brackets({}), we can shorten all of this and put it in a table. The code will look something like this:<syntaxhighlight lang="nix">
Using curly brackets({}), we can shorten all of this and put it in a table. The code will look something like this:<syntaxhighlight lang="nix">
inputs = {
inputs = {
   nixpkgs.url = "nixpkgs/<branch name>";
   nixpkgs.url = "github:NixOS/nixpkgs/<branch name>";
   hyprland = {
   hyprland = {
     url = "github:hyprwm/Hyprland";
     url = "github:hyprwm/Hyprland";
Line 205: Line 202:
and add <code>flake-compat</code> to the arguments of <code>outputs</code> attribute. Then you will be able to use <code>default.nix</code> like the following:
and add <code>flake-compat</code> to the arguments of <code>outputs</code> attribute. Then you will be able to use <code>default.nix</code> like the following:


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
(import (
(import (
   let
   let
     lock = builtins.fromJSON (builtins.readFile ./flake.lock);
     lock = builtins.fromJSON (builtins.readFile ./flake.lock);
   in fetchTarball {
    nodeName = lock.nodes.root.inputs.flake-compat;
     url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
   in
     sha256 = lock.nodes.flake-compat.locked.narHash; }
  fetchTarball {
) {
     url =
  src = ./.;
      lock.nodes.${nodeName}.locked.url
}).defaultNix
        or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.${nodeName}.locked.rev}.tar.gz";
</syntaxHighlight>
     sha256 = lock.nodes.${nodeName}.locked.narHash;
  }
) { src = ./.; }).defaultNix
</syntaxhighlight>


== Accessing flakes from Nix expressions ==
== Accessing flakes from Nix expressions ==


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:/path/to/directory").packages.x86_64-linux.default</code>, where 'directory' is the directory that contains your <code>flake.nix</code>.
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>.


== Making your evaluations pure ==
== Making your evaluations pure ==
Line 229: Line 229:
* Imports from channels like <code><nixpkgs></code> can be made pure by instead importing from the <code>output</code> function in <code>flake.nix</code>, where the arguments provide the store path to the flake's inputs:
* Imports from channels like <code><nixpkgs></code> can be made pure by instead importing from the <code>output</code> function in <code>flake.nix</code>, where the arguments provide the store path to the flake's inputs:


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
  outputs = { self, nixpkgs, ... }:
  outputs = { self, nixpkgs, ... }:
   {
   {
     nixosConfigurations.machine = nixpkgs.lib.nixosSystem {
     nixosConfigurations.machine = nixpkgs.lib.nixosSystem {
      # Note that you cannot put arbitrary configuration here: the configuration must be placed in the files loaded via modules
      system = "x86_64-linux";
       modules = [
       modules = [
         (nixpkgs + "/nixos/modules/<some-module>.nix")
         "${nixpkgs}/nixos/modules/<some-module>.nix"
         ./machine.nix
         ./machine.nix
       ];
       ];
     };
     };
   };
   };
</syntaxHighlight>
</syntaxhighlight>


== The nix flakes command ==
== The nix flakes command ==
Line 257: Line 255:
A basic nixos flake.nix could look like this:
A basic nixos flake.nix could look like this:


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{
{
  inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
   outputs = { self, nixpkgs }: {
   outputs = { self, nixpkgs }: {
     # replace 'joes-desktop' with your hostname here.
     # replace 'joes-desktop' with your hostname here.
     nixosConfigurations.joes-desktop = nixpkgs.lib.nixosSystem {
     nixosConfigurations.joes-desktop = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
       modules = [ ./configuration.nix ];
       modules = [ ./configuration.nix ];
     };
     };
   };
   };
}
}
</syntaxHighlight>
</syntaxhighlight>
If you want to pass on the flake inputs to external configuration files, you can use the <code>specialArgs</code> attribute:
If you want to pass on the flake inputs to external configuration files, you can use the <code>specialArgs</code> attribute:
<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{
{
   inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
   inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
   inputs.home-manager.url = github:nix-community/home-manager;
   inputs.home-manager.url = github:nix-community/home-manager;


   outputs = { self, nixpkgs, ... }@attrs: {
   outputs = { self, nixpkgs, ... }@inputs: {
     nixosConfigurations.fnord = nixpkgs.lib.nixosSystem {
     nixosConfigurations.fnord = nixpkgs.lib.nixosSystem {
       system = "x86_64-linux";
       specialArgs = { inherit inputs; };
      specialArgs = attrs;
       modules = [ ./configuration.nix ];
       modules = [ ./configuration.nix ];
     };
     };
   };
   };
}
}
</syntaxHighlight>
</syntaxhighlight>
Then, you can access the flake inputs from the file <code>configuration.nix</code> like this:
Then, you can access the flake inputs from the file <code>configuration.nix</code> like this:
<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{ config, lib, nixpkgs, home-manager, ... }: {
{ config, lib, inputs, ... }: {
   # do something with home-manager here, for instance:
   # do something with home-manager here, for instance:
   imports = [ home-manager.nixosModules.default ];
   imports = [ inputs.home-manager.nixosModules.default ];
   ...
   ...
}
}
</syntaxHighlight>
</syntaxhighlight>


{{Ic|nixos-rebuild}} also allows to specify different flake using the <code>--flake</code> flag (# is optional):
{{Ic|nixos-rebuild}} also allows to specify different flake using the <code>--flake</code> flag (# is optional):


<syntaxHighlight lang=console>
<syntaxhighlight lang="console">
$ sudo nixos-rebuild switch --flake '.#'
$ sudo nixos-rebuild switch --flake .
</syntaxHighlight>
</syntaxhighlight>


By default nixos-rebuild will use the currents system hostname to lookup the right nixos configuration in <code>nixosConfigurations</code>. You can also override this by using appending it to the flake parameter:
By default nixos-rebuild will use the currents system hostname to lookup the right nixos configuration in <code>nixosConfigurations</code>. You can also override this by using appending it to the flake parameter:


<syntaxHighlight lang=console>
<syntaxhighlight lang="console">
$ sudo nixos-rebuild switch --flake '/etc/nixos#joes-desktop'
$ sudo nixos-rebuild switch --flake /etc/nixos#joes-desktop
</syntaxHighlight>
</syntaxhighlight>


To switch a remote configuration, use:
To switch a remote host you can use:
<syntaxHighlight lang=bash>
<syntaxhighlight lang="bash">
$ nixos-rebuild --flake .#mymachine \
$ nixos-rebuild --flake .#mymachine \
   --target-host mymachine-hostname --build-host mymachine-hostname --fast \
   --target-host mymachine-hostname \
  --build-host mymachine-hostname --fast \
   switch
   switch
</syntaxHighlight>
</syntaxhighlight>


{{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 to the system pkgs on NixOS ==
== Pinning the registry on NixOS ==


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
  nix.registry = {
{ inputs, ... }:
     nixpkgs.to = {
{
      type = "path";
nix.registry = {
      path = pkgs.path;
     nixpkgs.flake = inputs.nixpkgs;
    };
   };
   };
</syntaxHighlight>
}
 
</syntaxhighlight>
{{warning|The above example seems to break nix's eval cache, and may slow down hdd systems significantly!}}


To make sure the registry entry is "locked", use the following:
To make sure the registry entry is "locked", use the following:
Line 349: Line 345:
Let’s say that your project has a <code>shell.nix</code> file that looks like this:
Let’s say that your project has a <code>shell.nix</code> file that looks like this:


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{ pkgs ? import <nixpkgs> { } }:
{
with pkgs;
  pkgs ? import <nixpkgs> { },
mkShell {
}:
   buildInputs = [
pkgs.mkShell {
    nixpkgs-fmt
   packages = [ pkgs.nixfmt ];
  ];


   shellHook = ''
   shellHook = ''
Line 361: Line 356:
   '';
   '';
}
}
</syntaxHighlight>
</syntaxhighlight>


Running nix-shell can be a bit slow and take 1-3 seconds.
Running nix-shell can be a bit slow and take 1-3 seconds.
Line 367: Line 362:
Now create a <code>flake.nix</code> file in the same repository:
Now create a <code>flake.nix</code> file in the same repository:


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{
{
  description = "my project description";
   inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
 
   inputs.flake-utils.url = "github:numtide/flake-utils";


   outputs = { self, nixpkgs, flake-utils }:
   outputs =
     flake-utils.lib.eachDefaultSystem
    { nixpkgs, ... }:
       (system:
     {
         let pkgs = nixpkgs.legacyPackages.${system}; in
      /*
        This example assumes your system is x86_64-linux
        change as neccesary
      */
       devShells.x86_64-linux =
         let
          pkgs = nixpkgs.legacyPackages.x86_64-linux;
        in
         {
         {
           devShells.default = import ./shell.nix { inherit pkgs; };
           default = pkgs.mkShell {
         }
            packages = [ pkgs.hello ];
      );
          };
         };
    };
}
}
</syntaxHighlight>
}
</syntaxhighlight>


Run git add flake.nix so that Nix recognizes it.
( If you're in a git repository run `git add flake.nix` so that Nix recognizes it. )


And finally, run <code>nix develop</code>. This is what replaces the old nix-shell invocation.
And finally, run <code>nix develop</code>. This is what replaces the old nix-shell invocation.
Line 394: Line 397:
=== Automatically switch nix shells with nix-direnv ===
=== Automatically switch nix shells with nix-direnv ===


You can easily switch nix shells when you cd into different projects with nix-direnv. [https://github.com/nix-community/nix-direnv View their guide here]
You can easily switch nix shells when you cd into different projects with [https://github.com/nix-community/nix-direnv nix-direnv].


== Pushing Flakes to Cachix ==
== Pushing Flakes to Cachix ==
Line 400: Line 403:
https://docs.cachix.org/pushing#flakes
https://docs.cachix.org/pushing#flakes


To push ''all'' flake outputs automatically, use [https://github.com/srid/devour-flake#usage devour-flake].
To push ''all'' flake outputs automatically, checkout [https://github.com/srid/devour-flake#usage devour-flake].


== Build specific attributes in a flake repository ==
== Build specific attributes in a flake repository ==
Line 414: Line 417:
=== Building flakes from a Git repo url with submodules ===
=== Building flakes from a Git repo url with submodules ===


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


<syntaxHighlight lang=console>
<syntaxhighlight lang="console">
$ nix build .?submodules=1#hello
nix build '.?submodules=1#hello'
</syntaxHighlight>
</syntaxhighlight>


See: https://github.com/NixOS/nix/pull/5434
See: https://github.com/NixOS/nix/pull/5434


== Importing packages from multiple channels ==
== Importing packages from multiple nixpkgs branches ==


A NixOS config flake skeleton could be as follows:
A NixOS config flake could be as follows:
<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{
{
   description = "NixOS configuration with two or more channels";
   description = "NixOS configuration with two or more channels";


   inputs = {
   inputs = {
     nixpkgs.url = "nixpkgs/nixos-21.11";
     nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
     nixpkgs-unstable.url = "nixpkgs/nixos-unstable";
     nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
   };
   };


   outputs = { self, nixpkgs, nixpkgs-unstable }:
   outputs =
    let
    { nixpkgs, nixpkgs-unstable, ... }:
      system = "x86_64-linux";
     {
      overlay-unstable = final: prev: {
        unstable = nixpkgs-unstable.legacyPackages.${prev.system};
        # use this variant if unfree packages are needed:
        # unstable = import nixpkgs-unstable {
        #  inherit system;
        #  config.allowUnfree = true;
        # };
 
      };
     in {
       nixosConfigurations."<hostname>" = nixpkgs.lib.nixosSystem {
       nixosConfigurations."<hostname>" = nixpkgs.lib.nixosSystem {
        inherit system;
         modules = [
         modules = [
           # Overlays-module makes "pkgs.unstable" available in configuration.nix
           {
          ({ config, pkgs, ... }: { nixpkgs.overlays = [ overlay-unstable ]; })
            nixpkgs.overlays = [
              (final: prev: {
                unstable = nixpkgs-unstable.legacyPackages.${prev.system};
                # use this variant if unfree packages are needed:
                # unstable = import nixpkgs-unstable {
                #  inherit system;
                #  config.allowUnfree = true;
                # };
              })
            ];
          }
           ./configuration.nix
           ./configuration.nix
         ];
         ];
Line 457: Line 459:
     };
     };
}
}
</syntaxHighlight>
</syntaxhighlight>


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
# NixOS configuration.nix, can now use "pkgs.package" or "pkgs.unstable.package"
# NixOS configuration.nix, can now use "pkgs.package" or "pkgs.unstable.package"
{ config, pkgs, ... }: {
{ pkgs, ... }:
   environment.systemPackages = [pkgs.firefox pkgs.unstable.chromium];
{
   environment.systemPackages = [
    pkgs.firefox
    pkgs.unstable.chromium
  ];
   # ...
   # ...
}
}
</syntaxHighlight>
</syntaxhighlight>If the variable <code>nixpkgs</code> points to the flake, you can also define <code>pkgs</code> with overlays with:
Same can be done with the NURs, as it already has an ''overlay'' attribute in the flake.nix of the project, you can just add <syntaxHighlight lang=nix>nixpkgs.overlays = [ nur.overlay ];</syntaxHighlight>


If the variable <code>nixpkgs</code> points to the flake, you can also define <code>pkgs</code> with overlays with:
<syntaxhighlight lang="nix">
 
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ /*the overlay in question*/ ]; };
<syntaxHighlight lang=nix>
</syntaxhighlight>
pkgs = import nixpkgs { overlays = [ /*the overlay in question*/ ]; };
</syntaxHighlight>


== Getting ''Instant'' System Flakes Repl ==
== Getting ''Instant'' System Flakes Repl ==
Line 478: Line 481:
How to get a nix repl out of your system flake:
How to get a nix repl out of your system flake:


<syntaxHighlight lang=text>
<syntaxhighlight lang="text">
# nix repl
$ nix repl
>> :lf /etc/nixos
 
>> nixosConfigurations.myhost.config
nix-repl> :lf /path/to/flake
{ ... }
Added 18 variables.
</syntaxHighlight>


Or out of your current flake:
nix-repl> nixosConfigurations.myHost.config.networking.hostName
<syntaxHighlight lang=text>
"myHost"
# nix repl
>> :lf .#
</syntaxHighlight>


You can then access to the inputs, outputs… For instance if you would like to check the default version of the kernel present in nixpgs:
<syntaxHighlight lang=text>
nix-repl> inputs.nixpkgs.legacyPackages.x86_64-linux.linuxPackages.kernel.version
"5.15.74"
</syntaxHighlight>


However, this won't be instant upon evaluation if any file changes have been done since your last configuration rebuild. Instead, if one puts:
</syntaxhighlight>


<syntaxHighlight lang=nix>
However, this won't be instant upon evaluation if any file changes have been done since your last configuration rebuild. Instead, if one puts:<syntaxHighlight lang=nix>
nix.nixPath = let path = toString ./.; in [ "repl=${path}/repl.nix" "nixpkgs=${inputs.nixpkgs}" ];
nix.nixPath = let path = toString ./.; in [ "repl=${path}/repl.nix" "nixpkgs=${inputs.nixpkgs}" ];
</syntaxHighlight>
</syntaxHighlight>