Come dividere /etc/nixos/configuration.nix in moduli separati?


14

Supponiamo di avere un file di configurazione NixOS molto semplice :

{ config, pkgs, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  # SOME STUFF
  environment.systemPackages = with pkgs; [ emacs gitFull ];
  # SOME STUFF
}

So che NixOS implementa un sistema di moduli e un modulo è un .nixfile. Ogni .nixfile deve contenere qualsiasi espressione Nix valida (ad es. Una funzione o un set). Ciò significa che il file di configurazione NixOS /etc/nixos/configuration.nixè esso stesso un modulo, contenente un'espressione Nix.

So anche che per rendere l'espressione Nix in un altro modulo visibile al modulo con cui sto lavorando, posso usare una importfunzione integrata .

Voglio dividere la dichiarazione dei pacchetti di sistema (l'elenco contenente emacse gitFull) in file packages.nix. Come posso dividere il file di configurazione di NixOS in moduli separati?

Risposte:


22

Espressioni Nix

Un'espressione Nix è come qualsiasi espressione linguaggio di programmazione: tutto ciò che restituisce un valore o una funzione. Un valore in questo caso può anche essere un elenco o un set. Poiché un modulo Nix (file con estensione .nix) può contenere qualsiasi espressione Nix, ci si aspetterebbe che il file di configurazione NixOS ( /etc/nixos/configuration.nix) contenga una singola espressione Nix come contenuto del file.

Il file di configurazione di NixOS contiene un'espressione Nix del modulo:

{config, pkgs, ...}: { /* various configuration options */ }

Se guardi da vicino, puoi vedere che è una funzione , perché le funzioni seguono il modulo pattern: form. Puoi anche vedere che è una funzione che accetta un set e restituisce un set. Ad esempio, se si dispone di una funzione f = {x, y}: {a = x + y;}, è possibile chiamarla comef {x=1; y=2;} e recuperare un set {a=3;}.

nixos-rebuild switchCiò significa che quando chiami , qualcosa chiama la funzione all'interno del file di configurazione NixOS con il set che deve contenere attributi configepkgs .

importazioni

Seguendo l'esempio di ./hardware-configuration.nix, il modo semplice per estrarre l'elenco di pacchetti in un modulo separato packages.nixè solo quello di estrarre l' environment.systemPackagesopzione e metterla ./packages.nixin importsopzione. Il tuo /etc/nixos/configuration.nixsarebbe simile a:

{ config, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      # Include the package list.
      ./packages.nix
    ];
  # SOME STUFF
  # SOME STUFF
}

Il tuo /etc/nixos/packages.nixsarebbe simile a:

{ pkgs, ... }:
{
  environment.systemPackages = with pkgs; [ emacs gitFull ];
}

Come funziona? Durante l'esecuzione nixos-rebuild switch, il processo che valuta le espressioni Nix e decide di installare i pacchetti e così via le chiamate configuration.nixcon un set di attributi, alcuni dei quali sonoconfig e pkgs.

Trova l'attributo importsall'interno del set restituito, quindi valuta ogni espressione Nix nei moduli che importscontiene con gli stessi argomenti ( config,pkgs , ecc).

Devi avere pkgscome argomento (o, tecnicamente parlando, un attributo di un set, che di per sé è un argomento) di una funzione packages.nix, perché, dal punto di vista del linguaggio Nix, il processo potrebbe o meno chiamare la funzione con l'insieme che contiene pkgs. In caso contrario, a quale attributo faresti riferimento durante l'esecuzionewith pkgs ?

È inoltre necessario disporre dei puntini di sospensione, poiché la funzione potrebbe essere chiamata con altri attributi, non solo pkgs .

Perché non c'è pkgsinconfiguration.nix ? Puoi averlo, ma se non ti riferisci a nessun punto del file, puoi tranquillamente ometterlo, poiché i puntini di sospensione li includerebbero comunque.

Aggiornamento di un attributo chiamando una funzione esterna

Un altro modo è solo quello di creare una funzione che restituisca un set con qualche attributo e il valore di quell'attributo che inseriresti environment.systemPackages. Questo è il tuo configuration.nix:

{ config, pkgs, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  # SOME STUFF
  environment.systemPackages = import ./packages.nix pkgs;
  # SOME STUFF
}

Il tuo packages.nix:

pkgs: with pkgs; [ emacs gitFull ]

import ./packages.nix pkgssignifica: carica e restituisce l'espressione Nix ./packages.nixe, poiché è una funzione, chiamala con un argomento pkgs. with pkgs; [ emacs gitFull ]è un'espressione con , porta l'ambito dell'espressione prima del punto e virgola all'espressione dopo il punto e virgola. Senza di essa, sarebbe [ pkgs.emacs pkgs.gitFull ].


1
Come vengono unite le importazioni? Usano recursiveUpdate o qualcosa del genere?
aij,

1
Esiste un modo per effettuare importazioni condizionate?
CMCDragonkai,

1
@CMCDragonkai il valore di importsè solo un elenco, quindi puoi aggiungere elementi a quello in modo condizionale, ad es.imports = [ ./foo.nix ./bar.nix ] ++ (if baz then [ ./quux.nix ] else []);
Warbo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.