charla-gpul-nixos/src/slides.md
2025-12-15 23:39:39 +01:00

10 KiB

title sub_title author
Introducción a Nix & NixOS Sistemas y paquetes que funcionan donde y cuando quieras Pedro Rey

Introducción

NixOS está de moda

La temida curva de aprendizaje de Nix(OS)

¿ Qué es Nix, NixOS, Nixpkgs ?

Muchos nombres, muy parecidos no?

image:width:50%

Nix

nix run nixpkgs#cowsay -- Soy un paquete de Nix
  • Gestor de paquetes
  • Declarativo
    • Reproducible
  • Sencillo

Declarativo?

El usuario especifica el estado final deseado y Nix se encarga de conseguirlo.

Nix, el lenguaje

Sólo existe por y para Nix, el gestor de paquetes: para describir paquetes y configuraciones, así como sus variantes y composiciones. No está pensado para casos de uso generales.

  • Sencillo
  • Funcional
  • Lazy
  • Turing completo
let
  fibonacci = n: 
    if n == 0 then
      0
    else if n == 1 then
      1
    else
      fibonacci(n - 1) + fibonacci(n - 2);
in
  fibonacci 12

Nixpkgs

  • Repositorio de paquetes en Nix (y módulos de NixOS)
  • Incluye tests, funciones de ayuda, etc.
  • Compilado y probado con Hydra
  • Subido a cache.nixos.org

De repology.org

NixOS

Logo de NixOS 25.11 "Xantusia" por Yohann Boniface

  • Nix como gestor de paquetes
  • OS as code
  • Se encarga solo de la parte declarativa
    • Datos dinámicos (estado) y carpeta de usuario, NO
{
    users.users.john= {
      isNormalUser  = true;
      home  = "/home/john";
      description  = "John Doe";
      extraGroups  = [ "wheel" "networkmanager" ];
      openssh.authorizedKeys.keys  = [ "ssh-dss AAAAB3Nza... john@foobar" ];
    };
}

Home Manager

  • Gestión de dotfiles
  • Independiente de NixOS
  • Por la comunidad
{
  programs.zsh = {
    enable = true;
    enableCompletion = true;
    autosuggestion.enable = true;
    syntaxHighlighting.enable = true;

    oh-my-zsh = {
      enable = true;
      plugins = ["git" "fzf"];
    };

    shellAliases = {
      c = "clear";
      cd = "z";
    };
  };

  programs.zoxide = {
    enable = true;
    enableZshIntegration = true;
  };

  programs.fzf.enable = true;
}

Ecosistema

  • Entornos de desarrollo
  • Entornos de compilación
  • Máquinas virtuales en la nube
  • Imáges de contenedores (more on that later)
  • NixOps, clan, colmena...
# Construir una imagen de docker para el paquete hello
pkgs.dockerTools.buildLayeredImage {
  name = "nix-hello"; 
  tag = "latest"; 
  contents = [ pkgs.hello ]; 
} 

Nix, el lenguaje

Modo interactivo

nix repl 
Welcome to Nix 2.13.3. Type :? for help.

nix-repl> 1 + 2
3

Espacios

let
 x = 1;
 y = 2;
in x + y
let x=1;y=2;in x+y

Attribute sets

Nix

{
  string = "hello";
  integer = 1;
  float = 3.141;
  bool = true;
  null = null;
  list = [ 1 "two" false ];
  attribute-set = {
    a = "hello";
    b = 2;
    c = 2.718;
    d = false;
  }; # comentarios
}

JSON

{
  "string": "hello",
  "integer": 1,
  "float": 3.141,
  "bool": true,
  "null": null,
  "list": [1, "two", false],
  "object": {
    "a": "hello",
    "b": 1,
    "c": 2.718,
    "d": false
  }
}
/// let a=
/// {
///   string = "hello";
///   integer = 1;
///   float = 3.141;
///   bool = true;
///   null = null;
///   list = [ 1 "two" false ];
///   attribute-set = {
///     a = "hello";
///     b = 2;
///     c = 2.718;
///     d = false;
///   }; 
/// };
/// in
a.attribute-set.c

let ... in ...

let
  a = 1;
in
a + a

with ...; ...

let
  a = {
    x = 1;
    y = 2;
    z = 3;
  };
in
with a; [ x y z ]

inherit ...

let
  x = 1;
  y = 2;
in
{
  inherit x y;
}

String interpoilation ${...}

let
  name = "mundo";
in
"hola ${name}"

Paths

/tmp/no/existe

Funciones

let
  f = x: x + 1;
in f 1
let
  f = x: x.a;
  v = { a = 1; };
in
f v

Librerías

builtins

  • Vienen con Nix
  • Escritas en C++
builtins.toString

pkgs.lib

  • En nixpkgs
  • Escritas en Nix
let
  pkgs = import <nixpkgs> {};
in
pkgs.lib.strings.toUpper "lookup paths considered harmful"

import

  • Parte de builtins
echo "1 + 2" > /tmp/file.nix
nix-instantiate --eval -E 'import /tmp/file.nix'

Impuridades

Path

echo "Hola mundo" > /tmp/data
nix-instantiate --eval -E '"${/tmp/data}"'

Fetchers

  • builtins.fetchurl
  • builtins.fetchTarball
  • builtins.fetchGit
  • builtins.fetchClosure
builtins.fetchurl "https://www.kernel.org/theme/images/logos/tux.png"

Derivaciones

  • Nix se usa para escribir derivaciones
  • Nix ejecuta derivaciones para producir resultados de compilación
  • Esos resultados se pueden usar como entrada para otras derivaciones
{ lib, stdenv, fetchurl }:

stdenv.mkDerivation rec {
  pname = "hello";
  version = "2.12";
  src = fetchurl {
    url = "mirror://gnu/${pname}/${pname}-${version}.tar.gz";
    sha256 = "1ayhp9v4m4rdhjmnl2bq3cibrbqqkgjbl3s7yk2nhlh8vj3ay16g";
  };
  meta = with lib; {
    license = licenses.gpl3Plus;
  };
}
let
  pkgs = import <nixpkgs> {};
in "${pkgs.hello}"

Flakes

  • Experimentales
    • Pero no como piensas
  • Simplemente un wrapper para otras configuraciones de Nix
  • flake.nix flake.lock
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
  };

outputs = { self, nixpkgs, ... }@inputs: {
    nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
      modules = [
        ./configuration.nix
      ];
    };
  };
}

Configurar NixOS

/etc/nixos/configuration.nix

{ config, pkgs, ... }:

{
  imports = [
    ./hardware-configuration.nix
  ];

  # ......

  nix.settings.experimental-features = [ "nix-command" "flakes" ];
  environment.systemPackages = with pkgs; [
    git
    vim
    wget
  ];
  environment.variables.EDITOR = "vim";

  # ......
}

Configurar NixOS con Flakes

/etc/nixos/flake.nix

{
  description = "A simple NixOS flake";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
  };

  outputs = { self, nixpkgs, ... }@inputs: {
    nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
      modules = [
        # Importamos lo que teníamos antes!
        ./configuration.nix
      ];
    };
  };
}

Anatomía de un modulo

  {lib, config, options, pkgs, ...}:
{
  # Importar otros modulos
  imports = [
    # ...
    ./xxx.nix
  ];

  for.bar.enable = true;
  # Otras declaraciones de opciones
  # ...
}
{
  config,
  pkgs,
  ...
}: {
  imports = [
    (import ./special-fonts-1.nix {inherit config pkgs;})
    ./special-fonts-2.nix
  ];

  fontconfig.enable = true;
}

lib.mkOverride, lib.mkDefault, and lib.mkForce

{
# ......

mkOverride = priority: content:
  { _type = "override";
    inherit priority content;
  };

mkOptionDefault = mkOverride 1500;
mkDefault = mkOverride 1000; 
mkImageMediaOverride = mkOverride 60; 
mkForce = mkOverride 50;
mkVMOverride = mkOverride 10; 

# ......
}

lib.mkOrder, lib.mkBefore, and lib.mkAfter

{
# ......

mkOrder = priority: content:
  { _type = "order";
    inherit priority content;
  };

mkBefore = mkOrder 500;
defaultOrderPriority = 1000;
mkAfter = mkOrder 1500;

# ......
}

Vamos a probar algunas cosas 🙃

Tips & tricks

  • Si usas Git, Nix ignora todos los archivos no trackeados.
  • sudo nix-collect-garbage --delete-old
  • sudo nix-store --optimise
{
  nix.gc = {
    automatic = true;
    dates = "weekly";
    options = "--delete-older-than 7d";
  };

  nix.settings.auto-optimise-store = true;
}

¿Preguntas?

Muchas Gracias ❤️

Repositorio

https://git.peprolinbot.com/peprolinbot/charla-gpul-nixos

Referencias

Otras recomendaciones

qrencode -t png -m 2 -s 30 -o - "https://git.peprolinbot.com/peprolinbot/charla-gpul-nixos/src/branch/main/enlace_final.md"