NIXOS EN 5 MINUTOS

Este se plantó hace 18 días y fué regado hace 0 días

NixOS en 5 minutos

Refs: 1 2 3 4 5 6 7 8 9 10 11 12 13 14

¿Que es NixOS?

NixOS es una distribución de Linux que se configura mediante ficheros y un lenguaje de programación declarativo. Esto quiere decir que, en lugar de configurar el sistema e instalar paquetes mediante comandos o interfaz gráfica, indicaremos en los ficheros de configuración que queremos instalar y cómo va a comportarse, y NixOS tratará de llevarlo a cabo.

Estos cambios se consideran estados del sistema, y podemos tanto cambiarlos en caliente (sin reiniciar) como volver a puntos anteriores de forma sencilla.

NixOS gira alrededor del gestor de paquetes Nix, y el languaje declarativo con el mismo nombre.

Todo esto, si lo combinamos con el uso de git, favorece un flujo de trabajo donde puedes mantener un repo con el estado exacto de tu sistema, o sistemas, haciendo que sea fácil reproducirlos o crear derivaciones.

Proceso de instalación de NixOS (minimal)

Mi primera instalación fué en mi homelab con la versión minimal de la ISO, siguiendo los tutoriales de TailScale10 y de Tony Banters1 y la wiki oficial de NixOS12. Luego actualicé la configuración para conectar a la máquina por SSH usando claves publicas. 13 14

Organización del disco

El primer paso de la instalación es particionar y formatear el disco duro mediante comandos (la ISO minimal no tiene interfaz).

Proceso de particionado y formateo del disco:
  1. Ejecutamos lsblk para encontrar el disco duro.

  2. Utilizando el comando cfdisk /dev/<nombre-disco>, creamos 3 particiones:

    • boot (1G, type EFI System)
    • swap (4G, type Linux swap)
    • root (resto del disco, type Linux filesystem).
  3. Aplicamos los cambios con write y salimos de la herramienta (exit).

  4. Lanzamos de nuevo lsblk para ver si se han creado las particiones, y luego las formateamos con los siguientes comandos:

  • Boot: mkfs.fat -F 32 -n <nombre-particion> /dev/<particion-boot>
  • Swap: mkswap -L <nombre-particion> /dev/<particion-swap
  • Root/Nixos: mkfs.ext4 -L <nombre-particion> /dev/<particion-root>

Por último, siguiendo con el tutorial de Tony Banters1, monté los discos en /mnt y ejecuté nixos-generate-config --root /mnt. Pero antes de finalizar con la instalación, hice ajustes en /mnt/etc/nixos/configuration.nix.

Configuración inicial e instalación

Configuración básica de configuration.nix antes de instalar el sistema:

  ...
  networking.hostname = <hostname>;
  networking.networkmanager.enable = true;

  time.timeZone = <zona-horaria>; # "List of tz database time zones" en Wikipedia*

  # Distribución del teclado en español para consola e interfaz gráfica
  console.keyMap = "es";
  services.xserver.xkb.layout = "es";

  services.xserver = {
    enable = true;
    autoRepeatDelay = 200;
    autoRepeatInterval = 35;
    windowManager.qtile.enable = true;
  };

  services.displayManager.ly.enable = true;

  # Descomentamos el bloque completo de users.users.<nombre-usuario>
  # (sólo cambiamos el nombre de usuario)

  environment.systemPackages = with pkgs; [
    wget
    vim
    git
  ];

  services.openssh = { # Sacado de la wiki de nixOS**
    enable = true;
    ports = [ <puerto> ];
    settings = {
      PasswordAuthentication = true; # Sólo hasta cargar las claves SSH con ssh-copy-id***
      AllowUsers = [ "<usuarios>" ];
      UseDns = true;
      X11Forwarding = false;
      PermitRootLogin = "prohibit-password";
    };
  };

  fonts.packages = with pkgs; [
    nerd-fonts.jetbrains-mono
  ];

  # Tony añade la instalación de Flakes aquí también, pero yo lo haré después.

(*) 11 (**) 13 (***) 14

Para terminar la instalación:
  1. Utilizamos el comando nixos-install desde /mnt.

  2. Introducimos la contraseña de root.

  3. Configuramos la contraseña para nuestro usuario:

    nixos-enter --root /mnt -c 'passwd <user>

Reiniciamos y listo.

Nix Flakes y nix-command

Ahora que tenemos el sistema instalado, lo primero es habilitar el uso de flakes y nix-command, que a día de hoy todavía son funciones experimentales, pero muy importantes.

¿Que son los flakes?

Son ficheros de configuración que utilizan Nix como lenguaje para declarar las dependencias y configuraciones del sistema, o incluso instrucciones de compilación.

Es muy similar a otros ficheros para declarar dependencias en proyectos de software, como package.json en Node.js o requirements.txt en Python. Del mismo modo, también genera un archivo .lock para “congelar” las versiones de los paquetes.

Esto último es super interesante ya que junto al flake.nix permite mantener los estados del sistema reproducibles y versionados.

nix-command por su parte es una utilidad que unifica varios comandos relacionados con el gestor de paquetes Nix.

Para habilitar ambas funciones necesitamos añadir la siguiente línea a /etc/nixos/configuration.nix:

nix.settings.experimental-features = ["nix-command" "flakes"];

Acto seguido, lanzamos nixos-rebuild switch para actualizar los cambios.

Si como yo, has creado un repo de dotfiles y modificado la copia de configuration.nix, tienes que indicar la ruta para ejecutar el comando:

nixos-rebuild switch -I nixos-config={ruta-a-configuration.nix}

Home Manager

En lugar de crear un flake.nix de 0, vamos a generar uno sencillo con el comando de instalación de Home Manager, que es la herramienta que nos falta para poner a punto esta primera versión del sistema.

¿Que es Home Manager?

Es un gestor de dotfiles, aplicaciones y configuraciones de usuario.

Se asemeja mucho a flakes, en tanto que también utiliza el lenguaje Nix y guarda las versiones de cada configuración, pero donde

Utiliza el lenguaje Nix y guarda las versiones de cada configuración.

Cuando recompilamos la configuración de usuario con home-manager switch, se limpia la configuración actual y se generan los enlaces simbólicos necesarios para aplicar la nueva.

Instalación de Home Manager con Flakes

Hay varias formas de instalar Home Manager, pero la decisión importante está en si queremos instalarlo separado del sistema o gestionado por este.

La principal diferencia entre un método u otro es el acoplamiento. Si instalamos Home Manager separado del sistema, facilita el poder cambiar e importar configuraciones sin sufrir ningún efecto secundario del sistema.

En mi caso, por comodidad y al estar todavía aprendiendo, y pensando también en mantener varias configuraciones para todas mis máquinas, he optado por la instalación integrada en el sistema.

En el manual de Home Manager, hay un comando que crea un flake.nix básico con la instalación de Home Manager:

nix flake new <ruta-destino> -t github:nix-community/home-manager#nixos

Antes de aplicar la configuración, modificaremos flake.nix para cambiar el nombre de usuario por el nuestro:

#--- flake.nix
...

nixosConfigurations = {
  <nombre-maquina> = nixpkgs.lib.nixosSystem  {
    ...
    
    home-manager.users.<nombre-usuario> = ./home.nix;
  }
};

Si ahora hacemos nixos-rebuild switch --flake {{ruta-flake}}, tendremos un error porque no existe el fichero home.nix, que es donde se definen las configuraciones de Home Manager.

En la página de instalación, hay una plantilla básica, pero podemos generar el fichero a través de la instalación standalone y después copiar el home.nix generado a nuestro flake:

nix run home-manager/master -- init

Esto genera tanto el flake.nix como el home.nix, pero como Home Manager va a ser gestionado por el sistema, sólo necesitamos el home.nix.

Estructura de flake.nix

Ahora que hemos generado tanto flake.nix como home.nix, podemos pararnos a analizar su estructura básica.

Ambos ficheros contienen una función con una entrada (bloque inputs) y una salida (bloque outputs). En inputs normalmente se declaran las dependencias, y en outputs la configuración del sistema o usuario.

#--- flake.nix
{
  description = "NixOS configuration with Home Manager";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager";

    # "follows"" fija la versión de home-manager a la misma que nixpkgs
    # para mantener la compatibilidad
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };
  
  outputs = 
    {nixpkgs, home-manager, ... }:
    {
      nixosConfigurations = {
        <hostname> = nixpkgs.lib.nixosSystem {
          system = "x86_64-linux";
          modules = [ 
            ./configuration.nix
            home-manager.nixosModules.home-manager
            {
              home-manager.useGlobalPkgs = true;
              home-manager.useUserPackages = true;
              home-manager.users.<nombre-usuario> = ./home.nix;
            };
          ];
        };
      };
    };
}

Estructura de home.nix

#--- home.nix

{ config, pkgs, ... }:

{
  home.username = "<nombre-usuario>";
  home.homeDirectory = "/home/<nombre-usuario>";

  home.stateVersion = <home-manager-version>;
  
  home.packages = with pkgs; [
    pkgs.hello
  ];

  home.file = {
    ...
  }

  home.sessionVariables = {
    ...
  };

  programs.home-manager.enable = true;
}

Footnotes

  1. https://www.youtube.com/watch?v=2QjzI5dXwDY 2 3

  2. https://www.youtube.com/watch?v=ACybVzRvDhs

  3. https://www.youtube.com/watch?v=IiyBeR-Guqw

  4. https://www.youtube.com/watch?v=bV3hfalcSKs

  5. https://www.youtube.com/watch?v=43VvFgPsPtY

  6. https://www.youtube.com/watch?v=OFGyKMSJzXY

  7. https://nixos-and-flakes.thiscute.world/

  8. https://nix.dev/tutorials/nix-language

  9. https://nix-community.github.io/home-manager/index.xhtml

  10. https://www.youtube.com/watch?v=9hni6rLfMTg 2

  11. https://en.wikipedia.org/wiki/List_of_tz_database_time_zones 2

  12. https://nixos.wiki/wiki/NixOS_Installation_Guide#Install_NixOS 2

  13. https://nixos.wiki/wiki/SSH 2 3

  14. https://www.unix.com/man_page/linux/1/ssh-copy-id/ 2 3