Flakes: Difference between revisions

Antono (talk | contribs)
m Small fix to flake example. Remove pkgs prefix since it uses with pkgs;
Pigs (talk | contribs)
NixOS configuration with flakes: move nixos section to new page
Line 415: Line 415:
== NixOS configuration with flakes ==
== NixOS configuration with flakes ==


=== Using nix flakes with NixOS === <!--T:68-->
It is possible to manage a [[NixOS]] system configuration using flakes, gaining the benefits of reproducible, declarative inputs and streamlined updates.


<!--T:69-->
For details and examples, see [[NixOS system configuration#Defining NixOS as a flake]].
By default, [[Nixos-rebuild|<code>nixos-rebuild switch</code>]] will read its [[Overview_of_the_NixOS_Linux_distribution#Declarative_Configuration system configuration|configuration]] from <code>/etc/nixos/flake.nix</code> if it is present.
 
<!--T:70-->
A basic [[NixOS]] flake.nix could look like this:
 
</translate>
<syntaxhighlight lang="nix">
{
  inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
  outputs = { self, nixpkgs }: {
    # replace 'joes-desktop' with your hostname here.
    nixosConfigurations.joes-desktop = nixpkgs.lib.nixosSystem {
      modules = [ ./configuration.nix ];
    };
  };
}
</syntaxhighlight>
<translate>
 
<!--T:158-->
If you want to pass on the flake inputs to external configuration files, you can use the <code>specialArgs</code> attribute:
 
</translate>
<syntaxhighlight lang="nix">
{
  inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
  inputs.home-manager.url = github:nix-community/home-manager;
 
  outputs = { self, nixpkgs, ... }@inputs: {
    nixosConfigurations.fnord = nixpkgs.lib.nixosSystem {
      specialArgs = { inherit inputs; };
      modules = [ ./configuration.nix ];
    };
  };
}
</syntaxhighlight>
<translate>
 
<!--T:159-->
Then, you can access the flake inputs from the file <code>configuration.nix</code> like this:
 
</translate>
<syntaxhighlight lang="nix">
{ config, lib, inputs, ... }: {
  # do something with home-manager here, for instance:
  imports = [ inputs.home-manager.nixosModules.default ];
  ...
}
</syntaxhighlight>
<translate>
 
<!--T:73-->
<code>nixos-rebuild</code> also allows to specify different flake using the <code>--flake</code> flag:
 
</translate>
<syntaxhighlight lang="console">
# nixos-rebuild switch --flake .
</syntaxhighlight>
<translate>
 
<!--T:75-->
By default <code>nixos-rebuild</code> will use the current system hostname to look up the right NixOS configuration in <code>nixosConfigurations</code>. You can also override this by using appending it to the flake parameter:
 
</translate>
<syntaxhighlight lang="console">
# nixos-rebuild switch --flake /etc/nixos#joes-desktop
</syntaxhighlight>
<translate>
 
<!--T:77-->
To switch a remote host you can use:
 
</translate>
<syntaxhighlight lang="bash">
$ nixos-rebuild --flake .#mymachine \
  --target-host mymachine-hostname \
  --build-host mymachine-hostname --fast \
  switch
</syntaxhighlight>
<translate>
 
<!--T:78-->
{{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-->
 
<!--T:111-->
A NixOS config flake could be as follows (replace <hostname> with your hostname):
 
</translate>
<syntaxhighlight lang="nix">
{
  description = "NixOS configuration with two or more channels";
 
inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
  };
 
  outputs =
    { nixpkgs, nixpkgs-unstable, ... }:
    {
      nixosConfigurations."<hostname>" = nixpkgs.lib.nixosSystem {
        modules = [
          {
            nixpkgs.overlays = [
              (final: prev: {
                unstable = nixpkgs-unstable.legacyPackages.${prev.system};
                # use this variant if unfree packages are needed:
                # unstable = import nixpkgs-unstable {
                #  inherit prev;
                #  system = prev.system;
                #  config.allowUnfree = true;
                # };
              })
            ];
          }
          ./configuration.nix
        ];
      };
    };
}
</syntaxhighlight>
<translate>
 
</translate>
<syntaxhighlight lang="nix">
# NixOS configuration.nix, can now use "pkgs.package" or "pkgs.unstable.package"
{ pkgs, ... }:
{
  environment.systemPackages = [
    pkgs.firefox
    pkgs.unstable.chromium
  ];
  # ...
}
</syntaxhighlight>
<translate>
 
<!--T:160-->
If the variable <code>nixpkgs</code> points to the flake, you can also define <code>pkgs</code> with overlays with:
 
</translate>
<syntaxhighlight lang="nix">
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ /*the overlay in question*/ ]; };
</syntaxhighlight>
<translate>
 
=== 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-->
How to get a nix repl out of your system flake:
 
</translate>
<syntaxhighlight lang="text">
$ nix repl
 
nix-repl> :lf /path/to/flake
Added 18 variables.
 
nix-repl> nixosConfigurations.myHost.config.networking.hostName
"myHost"
 
</syntaxhighlight>
<translate>
 
<!--T:122-->
However, this won't be instant upon evaluation if any file changes have been done since your last configuration rebuild. Instead, if one puts:
 
</translate>
<syntaxHighlight lang=nix>
nix.nixPath = let path = toString ./.; in [ "repl=${path}/repl.nix" "nixpkgs=${inputs.nixpkgs}" ];
</syntaxHighlight>
<translate>
 
<!--T:123-->
In their system <code>flake.nix</code> configuration file, and includes the following file in their root directory flake as <code>repl.nix</code>:
 
</translate>
<syntaxHighlight lang=nix>
let
  flake = builtins.getFlake (toString ./.);
  nixpkgs = import <nixpkgs> { };
in
{ inherit flake; }
// flake
// builtins
// nixpkgs
// nixpkgs.lib
// flake.nixosConfigurations
</syntaxHighlight>
<translate>
 
<!--T:125-->
(Don't forget to <code>git add repl.nix && nixos-rebuild  switch --flake "/etc/nixos"</code>)
Then one can run (or bind a shell alias):
 
</translate>
<syntaxHighlight lang=bash>
source /etc/set-environment && nix repl $(echo $NIX_PATH | perl -pe 's|.*(/nix/store/.*-source/repl.nix).*|\1|')</syntaxHighlight>
<translate>
 
<!--T:127-->
This will launch a repl with access to <code>nixpkgs</code>, <code>lib</code>, and the <code>flake</code> options in a split of a second.
 
<!--T:128-->
An alternative approach to the above shell alias is omitting <code>repl</code> from <code>nix.nixPath</code> and creating a [[Shell Scripts|shell script]]:
 
</translate>
<syntaxHighlight lang=nix>
nix.nixPath = [ "nixpkgs=${inputs.nixpkgs}" ];
environment.systemPackages = let
  repl_path = toString ./.;
  my-nix-fast-repl = pkgs.writeShellScriptBin "my-nix-fast-repl" ''
    source /etc/set-environment
    nix repl "${repl_path}/repl.nix" "$@"
  '';
in [
  my-nix-fast-repl
];
</syntaxHighlight>
<translate>


== Development tricks == <!--T:131-->
== Development tricks == <!--T:131-->