¿Cómo dividir /etc/nixos/configuration.nix en módulos separados?

Pregunta:

Supongamos que tengo un archivo de configuración de NixOS muy simple:

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

Sé que NixOS implementa un sistema de módulos y un módulo es un archivo .nix . Cada archivo .nix debe contener cualquier expresión Nix válida (por ejemplo, una función o un conjunto). Esto significa que el archivo de configuración de /etc/nixos/configuration.nix es en sí mismo un módulo que contiene una expresión de Nix.

También sé que para hacer que la expresión de Nix en otro módulo sea visible para el módulo con el que estoy trabajando, puedo usar una función de import incorporada .

Quiero dividir la declaración de los paquetes del sistema (la lista que contiene emacs y gitFull ) en el archivo packages.nix . ¿Cómo divido el archivo de configuración de NixOS en módulos separados?

Respuesta:

Expresiones de Nix

Una expresión de Nix es como cualquier expresión de lenguaje de programación: cualquier cosa que se evalúe como un valor o una función. En este caso, un valor también puede ser una lista o un conjunto. Como un módulo de Nix (archivo con extensión .nix ) puede contener cualquier expresión de Nix, es de esperar que el archivo de configuración de /etc/nixos/configuration.nix ( /etc/nixos/configuration.nix ) contenga una sola expresión de Nix como contenido del archivo.

El archivo de configuración de NixOS contiene una expresión de Nix de la forma:

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

Si miras de cerca, puedes ver que es una función , porque las funciones siguen el pattern: form . También puede ver que es una función que acepta un conjunto y devuelve un conjunto. Por ejemplo, si tiene una función f = {x, y}: {a = x + y;} , entonces podría llamarla como f {x=1; y=2;} y recupera un conjunto {a=3;} .

Eso significa que cuando llamas nixos-rebuild switch , algo llama a la función dentro del archivo de configuración de NixOS con el conjunto que debe contener los atributos config y pkgs .

importaciones

Siguiendo el ejemplo de ./hardware-configuration.nix , la forma simple de extraer la lista de paquetes en un módulo separado packages.nix es simplemente extraer la opción environment.systemPackages y colocar ./packages.nix en la opción de imports . Su /etc/nixos/configuration.nix se vería así:

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

Su /etc/nixos/packages.nix se vería así:

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

¿Cómo funciona? Cuando ejecuta nixos-rebuild switch , el proceso que evalúa las expresiones de Nix y decide instalar paquetes, etc., llama a configuration.nix con un conjunto de atributos, algunos de los cuales son config y pkgs .

Encuentra las imports atributos dentro del conjunto devuelto, por lo que evalúa cada expresión de Nix en los módulos que contiene las imports con los mismos argumentos ( config , pkgs , etc.).

Debe tener pkgs como argumento (o, técnicamente hablando, un atributo de un conjunto, que en sí mismo es un argumento) de una función en packages.nix , porque, desde la perspectiva del lenguaje Nix, el proceso podría o no llamar a la función con el set que contiene pkgs . Si no es así, ¿a qué atributo se referiría cuando se ejecuta with pkgs ?

También debe tener puntos suspensivos, porque la función puede llamarse con otros atributos, no solo pkgs .

¿Por qué no hay pkgs en configuration.nix ? Puede tenerlo, pero si no se refiere a él en ninguna parte del archivo, puede omitirlo con seguridad, ya que los puntos suspensivos los incluirían de todos modos.

Actualizar un atributo llamando a una función externa

Otra forma es simplemente hacer una función que devuelva un conjunto con algún atributo, y el valor de ese atributo que pondría dentro de environment.systemPackages . Esta es su 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
}

Su packages.nix :

pkgs: with pkgs; [ emacs gitFull ]

import ./packages.nix pkgs significa: cargar y devolver la expresión Nix en ./packages.nix y como es una función, llamarla con un argumento pkgs . with pkgs; [ emacs gitFull ] es una expresión con , trae el alcance de la expresión antes del punto y coma a la expresión después del punto y coma. Sin él, sería [ pkgs.emacs pkgs.gitFull ] .

Deja un comentario

Tu dirección de correo electrónico no será publicada.

Ir arriba