GRUB2: configurar el bootloader en Debian

GRUB2 (GRand Unified Bootloader versión 2) es el programa que el firmware arranca antes que el kernel. Su trabajo es localizar el kernel en el disco, cargar el initramfs y pasarle el control con los parámetros que tú hayas definido. En Debian, GRUB2 es el bootloader estándar en sistemas x86/amd64 tanto con BIOS como con UEFI.

El diseño de GRUB separa la configuración en dos capas. La primera es /etc/default/grub, un archivo de variables de shell que actúa como panel de control para el usuario —simple, legible, diseñado para edición manual. La segunda es /boot/grub/grub.cfg, el archivo que GRUB lee realmente durante el arranque —generado automáticamente por update-grub a partir de esa primera capa más los scripts en /etc/grub.d/. Nunca edites grub.cfg directamente: la próxima llamada a update-grub lo sobreescribe sin avisar.

Editas /etc/default/grub cuando necesitas cambiar el comportamiento del arranque: reducir el timeout en una máquina de producción que nunca necesita menú, añadir parámetros del kernel para depurar un problema de hardware, silenciar la salida de boot para un kiosko, o fijar el kernel por defecto después de una actualización que introdujo una regresión. Si tocas esas variables y olvidas ejecutar update-grub, el cambio no existe: el archivo que lees en el editor y el archivo que lee GRUB son dos cosas distintas.

Lo que se rompe cuando fallas aquí va desde lo molesto hasta lo catastrófico. Un GRUB_CMDLINE_LINUX_DEFAULT con un parámetro mal escrito puede impedir que el kernel monte el rootfs. Un GRUB_DEFAULT apuntando a un índice que ya no existe en el menú arranca el primer entry disponible en silencio. Y si corrompes /boot/grub/grub.cfg editándolo a mano y luego el sistema pierde corriente durante el boot, necesitas un live USB para recuperarte.

# Ver la configuración actual antes de tocar nada
cat /etc/default/grub

# Hacer una copia de seguridad con fecha — cuesta 0 segundos, salva horas
sudo cp /etc/default/grub /etc/default/grub.bak.$(date +%F)

# Editar la configuración principal
sudo nano /etc/default/grub

El archivo que verás tiene este aspecto por defecto en Debian Bookworm:

GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=`lsb_release -i -s 2>/dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""

Vamos a hacer tres cambios con propósito concreto: reducir el timeout a 2 segundos, añadir un parámetro de kernel para depurar un problema de memoria tardía en el arranque, y fijar el kernel anterior como default porque la última actualización rompió el módulo de red:

# /etc/default/grub — modificado para servidor con regresión en 6.1.0-21

# Entrada del menú que arranca por defecto.
# "saved" usa el último seleccionado manualmente; un número es el índice (0-based).
# Usamos el nombre exacto del entry para no depender del orden.
GRUB_DEFAULT="Advanced options for Debian GNU/Linux>Debian GNU/Linux, with Linux 6.1.0-20-amd64"

# Segundos que espera antes de arrancar automáticamente.
# En producción sin monitor, 2 es suficiente para intervenir si hace falta.
GRUB_TIMEOUT=2

# Estilo de presentación del timeout: "countdown" muestra la cuenta regresiva visible.
# "hidden" lo oculta y pulsar Shift lo muestra; útil en desktops para que arranque rápido.
GRUB_TIMEOUT_STYLE=countdown

GRUB_DISTRIBUTOR=`lsb_release -i -s 2>/dev/null || echo Debian`

# Parámetros pasados al kernel en boot normal (con initramfs).
# Quitamos "splash" para ver la salida real del kernel; añadimos "memtest=4"
# para que el kernel reporte problemas de memoria en dmesg desde el inicio.
# "loglevel=7" activa todos los mensajes del kernel, equivale a pr_debug.
GRUB_CMDLINE_LINUX_DEFAULT="quiet loglevel=7 memtest=4"

# Parámetros que se añaden en TODOS los modos (normal + recovery).
# Aquí va lo que necesitas siempre, independientemente del entry.
GRUB_CMDLINE_LINUX=""

# Si tienes varios SO, os-prober los detecta. En servidores puros, desactívalo:
# evita que GRUB busque en discos de datos y ralentice update-grub.
GRUB_DISABLE_OS_PROBER=true

Con el archivo guardado, regeneramos grub.cfg:

# update-grub es un wrapper de grub-mkconfig -o /boot/grub/grub.cfg
sudo update-grub

# Verifica que el entry que pusiste en GRUB_DEFAULT aparece literalmente en el cfg
# Si no lo encuentra, GRUB arrancará el entry 0 sin error visible
grep "menuentry\|set default" /boot/grub/grub.cfg | head -20

Si el sistema arranca con UEFI en lugar de BIOS clásica, los archivos de GRUB están bajo /boot/efi/EFI/debian/ y el binario que ejecuta el firmware es /boot/efi/EFI/debian/grubx64.efi. update-grub sigue siendo el comando correcto; la diferencia es transparente para este flujo.

# Confirma en qué modo arrancó el sistema actual
[ -d /sys/firmware/efi ] && echo "UEFI" || echo "BIOS/Legacy"

# En sistemas UEFI, las entradas del firmware se gestionan con efibootmgr, no con GRUB_DEFAULT.
# Para cambiar el orden de boot entre SO distintos, usa:
sudo efibootmgr -v

Qué hace exactamente cada decisión del ejemplo

GRUB_DEFAULT con nombre completo: el índice numérico (0, 1, 2) corresponde al orden en que grub-mkconfig genera las entradas, y ese orden puede cambiar cada vez que instalas o eliminas un kernel. Usar el string exacto del menuentry es frágil también —el nombre tiene que coincidir carácter por carácter, incluyendo espacios y versión— pero al menos es explícito y visible. El formato "submenu>entry" que usamos en el ejemplo es necesario porque los kernels alternativos en Debian aparecen dentro del submenú “Advanced options”; si escribes solo el nombre del entry sin el prefijo del submenú, GRUB no lo encuentra.

GRUB_CMDLINE_LINUX_DEFAULT vs GRUB_CMDLINE_LINUX: la diferencia es sutil pero importante. CMDLINE_LINUX_DEFAULT se aplica solo al entry normal (el primero del menú, el que arranca automáticamente). CMDLINE_LINUX se aplica a todos los entries generados, incluyendo el modo recovery. Si añades un parámetro en CMDLINE_LINUX_DEFAULT y luego arrancas en recovery, ese parámetro no estará. Para parámetros de seguridad o de hardware que debes tener siempre —como intel_iommu=on o nomodeset— ponlos en CMDLINE_LINUX.

loglevel=7: el kernel usa niveles de 0 (emergencia) a 7 (debug). El default de Debian en boot normal es 4 (advertencias). Subir a 7 temporalmente para diagnosticar un problema de driver es legítimo; recuerda bajarlo después porque ralentiza el boot y llena el buffer del kernel más rápido de lo que dmesg puede leer.

GRUB_DISABLE_OS_PROBER=true: en Debian Bookworm, os-prober está desactivado por defecto precisamente porque en entornos cloud o con muchos discos montados puede detectar particiones de datos como sistemas operativos y generar entries incorrectos en el menú. En un equipo de escritorio con Windows en otro disco, necesitas GRUB_DISABLE_OS_PROBER=false o simplemente eliminar esa línea para que os-prober funcione.

El grep de verificación al final: update-grub no falla aunque GRUB_DEFAULT apunte a un entry inexistente. El error se manifiesta silenciosamente en el siguiente boot cuando arranca un kernel diferente al esperado. Comprobar que el string que pusiste en GRUB_DEFAULT aparece literalmente en grub.cfg es el único modo de confirmar que la configuración es correcta antes de reiniciar.

[Ubuntu]: En Ubuntu 22.04+, /etc/default/grub.d/ tiene archivos adicionales que pueden sobreescribir variables definidas en /etc/default/grub. Si un cambio no tiene efecto después de update-grub, revisa ese directorio. El wrapper update-grub es idéntico en ambos sistemas.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio