:::note Asumo que usted ya sabe lo que es el Secure Boot, el TPM 2.0 y porqué los quiere habilitar. :::

Existen sólo dos prerrequisitos para esta guía:

  1. Usar flakes para tu configuración de NixOS
  2. Tener el Secure Boot en «Setup Mode» 1

Activar el Secure Boot

Antes que nada, confirmemos si el Secure Boot está activado como se debe

$ bootctl status
 System:
    Firmware: UEFI 2.80 (American Megatrends 5.25)
    Firmware Arch: x64
    Secure Boot: disabled (setup)
    TPM2 Support: yes
    Measured UKI: yes
    Boot into FW: supported

Las dos líneas importantes son TPM2 Support y Secure Boot, la primera es autoexplicativa. La segunda debe de decir disabled (setup) para continuar con esta guía. Otros posibles valores son disabled (disabled) o disabled (unsupported). La única fatal es la última, pues significa que su sistema no cuenta con Secure Boot, todas las demás significa que debe seguir rascando en la BIOS.

Generar las llaves criptográficas

Entraremos en una shell con sbctl, pues servirá en caso de que se equivoque a mitad del proceso.

$ nix shell nixpkgs#sbctl

Una vez dentro,

$ sudo sbctl create-keys

Esto debería crear una bola de archivos bajo /var/lib/sbctl

$ tree /var/lib/sbctl
 /var/lib/sbctl
├── keys
   ├── db
   ├── db.key
   └── db.pem
   ├── KEK
   ├── KEK.key
   └── KEK.pem
   └── PK
       ├── PK.key
       └── PK.pem
├── files.json
└── 󰡯 GUID

Agregue lanzaboote a su flake

# ...
inputs = {
  lanzaboote = {
    url = "github:nix-community/lanzaboote";
    inputs.nixpkgs.follows = "nixpkgs";
  };
};
# ...

Ahora, lo que usted hará es lo objetivamente correcto y generar un módulo dedicado al Secure Boot que importará de alguna manera, ¡sea ordenado con su configuración de Nix!

{
  lib,
  inputs,
  pkgs,
  ...
}: {
  imports = [
    inputs.lanzaboote.nixosModules.lanzaboote
  ];
 
  environment.systemPackages = [
    # Para uso futuro, lo vas a necesitar. Créeme.
    pkgs.sbctl
  ];
 
  boot = {
    # Actualmente, Lanzaboote reemplaza el módulo de systemd-boot.
    # Normalmente esto está en true en los configuration.nix
    # autogenerados, por lo que lo forzamos a false.
    loader.systemd-boot.enable = lib.mkForce false;
 
    lanzaboote = {
      enable = true;
      pkiBundle = "/var/lib/sbctl/";
    };
  };
}

Una vez que agregue esta confiugración, reconstruya su sistema. Para confirmar si todo esto funcionó:

$ sudo sbctl verify
Verifying file database and EFI images in /boot...
 /boot/EFI/BOOT/BOOTX64.EFI is signed
 /boot/EFI/Linux/nixos-generation-1013-ri3ncrqino2kv533utzhokre2e2jhghprn2g7x5k23336vvgniwa.efi is signed
 /boot/EFI/Linux/nixos-generation-1013-specialisation-ollamaNoGPU-mqpm5ulo76adzgn4rlk57q2hmy5756zkjkqghuc33uum73jog25q.efi is signed
 /boot/EFI/Linux/nixos-generation-1014-2knmqls4x5mxcjzvbshhpkkg2em6qv3itnqdnvuspb6ipj2xhyaa.efi is signed
 /boot/EFI/Linux/nixos-generation-1014-specialisation-ollamaNoGPU-kxnw4ou7ewmh5ganp4crgxnbax7zljplvoe46ifkisrvcnt5qpmq.efi is signed
 /boot/EFI/Linux/nixos-generation-1015-ri3ncrqino2kv533utzhokre2e2jhghprn2g7x5k23336vvgniwa.efi is signed
 /boot/EFI/Linux/nixos-generation-1015-specialisation-ollamaNoGPU-mqpm5ulo76adzgn4rlk57q2hmy5756zkjkqghuc33uum73jog25q.efi is signed
 /boot/EFI/nixos/kernel-6.11.8-qj7md4zvdijjzi2szevrvi3pnvszxkc4andpvr4aqxzmdcebysoa.efi is not signed
 /boot/EFI/systemd/systemd-bootx64.efi is signed

La salida debería verse similar a esto, despreocúpese de que los kernels no están firmados, eso es normal.

Lanzaboote agregó sus llaves criptográficas y firmó todas las generaciones de NixOS, ahora solo queda un último paso para activar el Secure Boot:

$ sudo sbctl enroll-keys --microsoft

Reinicie y verifique:

$ bootctl status
System:
      Firmware: UEFI 2.80 (American Megatrends 5.27)
 Firmware Arch: x64
   Secure Boot: enabled (user)
  TPM2 Support: yes
  Measured UKI: yes
  Boot into FW: supported

Si su salida no luce así, revise sus pasos y consulte la documentación de Lanzaboote.

Desbloquear LUKS con TPM

Ahora que pasó la parte difícil, activar esto es trivial. Primero necesita que systemd corra en la fase 1 del booteo.

# ...
boot.initrd.systemd.enable = true;
# ...

Después corra

sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+2+7+12 --wipe-slot=tpm2 <dispositivo>

La flag importante aquí es --tpm2-pcrs=0+2+7+12, esto le especifica a systemd lo que debe checar antes de que permitir que el chip TPM desbloquee el disco. Estos se llaman PCRs, aquí una pequeña tabla uqe explica cada uno:

PCRDescripción
0Código de Firmware ejecutable
2Código extendido ejecutable
7Estado del Secure Boot
12CLI del kernel sobreescrita, Credenciales

Para más información, consulte la página de la Arch Wiki.

Ahora puede reiniciar su sistema y no debería necesitar introducir la contraseña del LUKS.

Footnotes

  1. El nombre de este modo puede variar según el firmware de su motherboard, queda como ejercicio al lector descbrir esto.