Creación de la máquina

Vamos a crear una máquina virtual en virt-manager, le daremos 2GB de RAM, 2 CPUs y 15GB de disco. Antes de iniciar la instalación es muy importante que en el firmware pongamos que sea de tipo UEFI y con la opción de Secure Boot.

Selección del firmware UEFI con Secure Boot en virt-manager

Secure boot

Si cuando hemos iniciado la máquina lo primero que tendremos que hacer es ver si tenemos el Secure Boot activado; si no, tendremos que hacer lo siguiente:

1sudo dmesg | grep -i "secure boot"

Si no lo está, apagamos la VM:

1sudo virsh shutdown <nombredlamaquina>

Eliminamos el NVRAM actual si existe:

1sudo rm /var/lib/libvirt/qemu/nvram/Kernel_VARS.fd

Y copiamos el NVRAM con claves Microsoft:

1sudo cp /usr/share/OVMF/OVMF_VARS_4M.ms.fd /var/lib/libvirt/qemu/nvram/Kernel_VARS.fd

Y ajustamos permisos:

1sudo chown libvirt-qemu:kvm /var/lib/libvirt/qemu/nvram/Kernel_VARS.fd
2sudo chmod 600 /var/lib/libvirt/qemu/nvram/Kernel_VARS.fd

Y cuando encendamos ahora la máquina, nos aparecerá activado ya:

Secure Boot deshabilitado antes del cambio de NVRAM, y habilitado tras copiar las claves Microsoft y reiniciar

Instalación de las dependencias

Instalar todas las herramientas necesarias para compilar el kernel, crear paquetes .deb, firmar binarios y gestionar el arranque UEFI.

1sudo apt update && sudo apt install build-essential libncurses-dev bison flex libdw-dev libssl-dev libelf-dev bc xz-utils fakeroot debhelper locales curl rsync sbsigntool lvm2 efibootmgr -y

Explicación de los paquetes más importantes:

  • build-essential: Compilador GCC, make y herramientas básicas de compilación
  • libssl-dev, libelf-dev: Necesarios para firmar módulos del kernel y trabajar con binarios ELF
  • sbsigntool: Herramienta para firmar el kernel con claves Secure Boot
  • fakeroot, debhelper: Permiten crear paquetes .deb sin ser root
  • lvm2: Soporte para volúmenes lógicos en el initramfs
  • efibootmgr: Gestiona entradas de arranque UEFI desde Linux

Crear entorno de trabajo

Organizar el espacio de trabajo en /usr/src, ubicación estándar para código fuente del kernel en sistemas Linux.

1sudo mkdir /usr/src/compilacion
2cd /usr/src/compilacion

Descargar código fuente del kernel

Obtener el código fuente oficial del kernel Linux desde kernel.org para compilarlo.

Primero, buscamos la última versión estable 6.12.x:

1curl -s https://cdn.kernel.org/pub/linux/kernel/v6.x/ | grep -o 'linux-6\.12\.[0-9]*\.tar\.xz' | sort -V | tail -1

Explicación del comando:

  • curl -s: Descarga silenciosamente el listado HTML
  • grep -o: Extrae solo las coincidencias del patrón
  • sort -V: Ordena por versión
  • tail -1: Muestra la última (más reciente)

Búsqueda de la última versión estable del kernel 6.12.x con curl

Ahora descargamos la versión encontrada:

1sudo wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.68.tar.xz

Y descomprimimos el archivo:

1sudo tar -xf linux-6.12.68.tar.xz
2cd linux-6.12.68

Configurar el kernel

Adaptar la configuración del kernel actual a la nueva versión, eliminando módulos innecesarios para acelerar la compilación.

1sudo cp /boot/config-$(uname -r) .config

Este archivo .config contiene todas las opciones de compilación del kernel actual. Es un punto de partida seguro porque ya sabemos que funciona con nuestro hardware.

1sudo make olddefconfig

olddefconfig toma la .config antigua y la adapta a la nueva versión del kernel, usando valores por defecto para opciones nuevas sin hacer preguntas interactivas.

1sudo make localmodconfig

localmodconfig analiza qué módulos están cargados actualmente (lsmod) y desactiva todos los demás en el .config. Esto reduce el tiempo de compilación.

Compilar el kernel

Compilar el código fuente del kernel y crear paquetes .deb instalables.

1time sudo make bindeb-pkg -j$(nproc)
  • time: Mide cuánto tarda la compilación
  • make bindeb-pkg: Compila el kernel y crea paquetes .deb
  • -j$(nproc): Usa todos los núcleos de CPU disponibles
  • $(nproc): Devuelve el número de CPUs

Resultado de la compilación del kernel con make bindeb-pkg: paquetes generados y tiempo total

Instalar paquetes del kernel

Vamos a instalar el kernel compilado, sus headers y bibliotecas en el sistema.

1cd ..
2sudo dpkg -i linux-*.deb

Verás varios archivos .deb:

  • linux-image-6.12.68_*.deb: El kernel en sí
  • linux-headers-6.12.68_*.deb: Headers para compilar módulos externos
  • linux-libc-dev_*.deb: Headers para desarrollo de aplicaciones

Firma del Kernel para Secure Boot

Organizar las claves de firma en un directorio dedicado para mantenerlas seguras y localizadas.

1sudo mkdir -p /usr/src/compilacion/claves
2cd /usr/src/compilacion/claves

Generar par de claves

Crear un par de claves RSA (pública y privada) para firmar digitalmente nuestro kernel. Secure Boot verificará esta firma antes de permitir el arranque.

1sudo openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv \
2-outform DER -out MOK.der -days 3650 \
3-subj "/CN=JoseManuel Kernel CA/" \
4-nodes

Explicación de parámetros:

  • -x509: Crea un certificado autofirmado
  • -newkey rsa:2048: Genera clave RSA de 2048 bits (estándar de seguridad)
  • -keyout MOK.priv: Archivo de clave privada (mantener en secreto)
  • -outform DER -out MOK.der: Certificado público en formato binario DER
  • -days 3650: Válido por 10 años
  • -subj "/CN=...": Nombre identificativo del certificado
  • -nodes: No encriptar la clave privada con contraseña (simplifica el proceso)

Convertir formato de clave

Convertir el certificado de formato binario (DER) a formato texto (PEM) para usarlo con sbsign:

1sudo openssl x509 -inform der -in MOK.der -out MOK.pem

El formato PEM es más compatible con herramientas de firma. Contiene el mismo certificado pero codificado en Base64 entre delimitadores BEGIN/END CERTIFICATE.

Importar clave en MOK

Registrar nuestra clave en el sistema MOK (Machine Owner Key) para que Secure Boot confíe en ella.

1sudo mokutil --import MOK.der

Esta contraseña es temporal y solo se usa una vez en el siguiente reinicio para confirmar que realmente queremos añadir esta clave al firmware. MOK es un sistema que permite a los propietarios de máquinas añadir sus propias claves de confianza sin desactivar Secure Boot.

Firmar el kernel

Añadir una firma digital al kernel usando nuestra clave privada. Secure Boot verificará esta firma con el certificado público enrollado en MOK.

1sudo sbsign --key MOK.priv --cert MOK.pem \
2/boot/vmlinuz-6.12.68 \
3--output /boot/vmlinuz-6.12.68.signed
4
5sudo mv /boot/vmlinuz-6.12.68.signed /boot/vmlinuz-6.12.68

Explicación:

  • sbsign: Herramienta de firma de binarios UEFI
  • --key MOK.priv: Usa nuestra clave privada para firmar
  • --cert MOK.pem: Incluye el certificado público en la firma
  • Se crea un archivo .signed que luego reemplaza al original

Verificar firma

Confirmar que el kernel se firmó correctamente antes de reiniciar.

1sudo sbverify --cert MOK.pem /boot/vmlinuz-6.12.68

sbverify comprueba que la firma digital del kernel corresponde a nuestro certificado. Si falla aquí, no arrancaría con Secure Boot activo.

Actualizar GRUB

Regenerar la configuración de GRUB para que incluya el nuevo kernel firmado en el menú de arranque:

1sudo update-grub

GRUB busca todos los kernels en /boot y genera /boot/grub/grub.cfg con las entradas de arranque.

Reiniciar para enrollar la clave MOK

Arrancar en el MOK Manager para confirmar e inscribir nuestra clave en el firmware UEFI.

1sudo reboot

Aparecerá una pantalla azul “Perform MOK management” ANTES de que arranque el sistema operativo.

  1. Selecciona “Enroll MOK”

Pantalla Perform MOK management con Enroll MOK seleccionado

  1. Selecciona “Continue”

Pantalla Enroll MOK con la opción View key 0 y Continue

  1. Selecciona “Yes”

Pantalla de confirmación Enroll the key(s) con Yes seleccionado

  1. Ingresa la contraseña que pusiste antes

Pantalla de introducción de la contraseña temporal del MOK

  1. Selecciona Reboot

Pantalla final de Perform MOK management con Reboot seleccionado

MOK Manager es una interfaz pre-boot que permite gestionar claves de confianza. La contraseña evita que alguien con acceso físico añada claves maliciosas sin tu consentimiento.

Verificar arranque con nuevo kernel

1ssh josemanuel@192.168.122.143
2uname -r

uname -r muestra la versión del kernel actualmente en ejecución. Si muestra tu versión compilada, todo funciona correctamente.

Conexión SSH a la máquina y confirmación de que corre el kernel 6.12.68 compilado

Verificar Secure Boot y clave MOK

Confirmar que Secure Boot sigue activo y que nuestra clave está correctamente enrollada en el firmware.

Verificar Secure Boot activo:

1sudo dmesg | grep -i "secure boot"

Ver estado de Secure Boot:

1sudo mokutil --sb-state

Listar claves MOK enrolladas:

1mokutil --list-enrolled | grep -A 10 "JoseManuel"

Estos comandos verifican tres cosas: (1) que el kernel detectó Secure Boot activo al arrancar, (2) que el firmware UEFI tiene Secure Boot habilitado, y (3) que nuestra clave está en la base de datos MOK del firmware.

Salida de dmesg, mokutil –sb-state y mokutil –list-enrolled confirmando la clave JoseManuel Kernel CA enrollada

Arranque Directo sin GRUB

Copiar kernel e initrd a EFI

Colocar el kernel firmado y el initramfs en la partición EFI para que sean accesibles directamente por el firmware UEFI.

1sudo cp /boot/vmlinuz-6.12.68 /boot/efi/EFI/debian/
2sudo cp /boot/initrd.img-6.12.68 /boot/efi/EFI/debian/

Cuando usas EFI Stub para arranque directo, el kernel debe tener extensión .efi para que el firmware UEFI lo reconozca correctamente como un ejecutable EFI.

1sudo mv /boot/efi/EFI/debian/vmlinuz-6.12.68 /boot/efi/EFI/debian/vmlinuz-6.12.68.efi

EFI Stub es una característica del kernel Linux que lo convierte en un ejecutable EFI válido. Esto permite que el firmware UEFI cargue el kernel directamente, sin intermediarios como GRUB.

Obtener UUID de la partición raíz

Identifica el UUID único de tu partición raíz para pasárselo al kernel en los parámetros de arranque.

1lsblk -f

El UUID identifica de forma única una partición. Es más confiable que usar /dev/vd* porque los nombres de dispositivo pueden cambiar entre reinicios.

Obtenemos su UUID:

1export UUID=$(sudo blkid -s UUID -o value /dev/vda2)

Creamos la entrada UEFI para arranque directo:

1sudo efibootmgr --create --disk /dev/vda --part 1 \
2  --label "Kernel arranque directo" \
3  --loader '\EFI\debian\vmlinuz-6.12.68.efi' \
4  --unicode "root=UUID=$UUID ro initrd=\\EFI\\debian\\initrd.img-6.12.68"

Explicación de parámetros:

  • --create: Crea una nueva entrada de arranque
  • --disk /dev/vda --part 1: Especifica dónde está la partición EFI
  • --label "Kernel arranque directo": Nombre que aparecerá en el menú de arranque UEFI
  • --loader '\EFI\debian\vmlinuz-6.12.68.efi': Ruta al ejecutable EFI en la partición
  • --unicode "...": Parámetros que se pasan al kernel:
    • root=UUID=$UUID: Le dice al kernel dónde está la partición raíz
    • ro: Monta en solo lectura inicialmente
    • initrd=\\EFI\\debian\\initrd.img-6.12.68: Ruta al initramfs

Comprobación de particiones con lsblk -f, exportación del UUID y creación de la entrada de arranque con efibootmgr

Verificar entradas de arranque

Revisar todas las entradas de arranque UEFI y localizar nuestra entrada recién creada.

1sudo efibootmgr -v

Listado completo de entradas de arranque UEFI, con Kernel arranque directo entre ellas

Como vemos, nuestra entrada creada está en primer lugar del BootOrder.

Copiar certificado a partición EFI

Copiamos la clave MOK a la partición EFI:

1sudo cp /usr/src/compilacion/claves/MOK.der /boot/efi/

Ahora reiniciamos y verificamos el arranque directo. Comprobar que el sistema arranca directamente con nuestro kernel sin pasar por GRUB:

1sudo reboot

Enrollar certificado en el firmware UEFI

Al reiniciar, el sistema no encontrará un bootloader válido y entrará automáticamente en la configuración UEFI. Aquí debemos enrollar nuestro certificado en la base de datos DB del firmware:

  1. El sistema arranca en el menú de configuración UEFI
  2. Navega a Device Manager → Secure Boot Configuration → Secure Boot Mode → Custom Mode

Menú principal UEFI con Device Manager seleccionado

Device Manager con Secure Boot Configuration seleccionado

Secure Boot Configuration cambiando Secure Boot Mode de Standard a Custom Mode

  1. Selecciona Custom Secure Boot Options → DB Options → Enroll Signature

Secure Boot Configuration con Custom Secure Boot Options seleccionado

Custom Secure Boot Options con DB Options seleccionado

DB Options con Enroll Signature seleccionado

  1. Selecciona Enroll Signature Using File

Pantalla Enroll Signature con Enroll Signature Using File seleccionado

Navega en el explorador de archivos hasta encontrar MOK.der en la partición EFI:

File Explorer mostrando la partición sin etiqueta donde está MOK.der

Selecciona el archivo MOK.der y presiona Enter:

File Explorer con MOK.der seleccionado dentro de la carpeta EFI

Selecciona Commit Changes and Exit:

Pantalla Enroll Signature con MOK.der cargado y Commit Changes and Exit seleccionado

Verificación del arranque directo

Una vez reiniciado el sistema, ya arrancará directo sin pantalla de GRUB:

Conexión SSH tras el arranque directo: uname -r, cat /proc/cmdline con el UUID y el initrd, y Secure Boot enabled