Hasta ahora srv-tramontana siempre ha arrancado. Has instalado, configurado, endurecido y defendido un sistema partiendo de la premisa de que, al encenderlo, aparece un prompt. Esta lección rompe esa premisa, y lo hace en los dos sentidos: primero entenderás qué ocurre exactamente entre pulsar el botón y ver el prompt, y después aprenderás a intervenir cuando esa cadena se rompe.

Es la habilidad que separa a quien reinstala de quien arregla. Un fstab con un UUID equivocado, un initramfs que no incluye el módulo de LUKS, un GRUB sobrescrito por otro sistema operativo, una contraseña de root perdida: todos son problemas de cinco minutos si sabes dónde intervenir, y una reinstalación de ocho horas si no. Y como el Módulo 5 te enseñó a modificar fstab y el 6 a cifrar un volumen con LUKS, ya tienes en la máquina exactamente los ingredientes que provocan estos fallos.

Nota sobre el laboratorio. Varios de los procedimientos de esta lección requieren la consola de la VM, no una sesión SSH: cuando el sistema no arranca, no hay red. Ten claro cómo abrir la consola de VirtualBox antes de empezar, y haz un snapshot nuevo (06-antes-de-arranque) — vas a romper el arranque a propósito.

Contenido

  1. La cadena de arranque completa
  2. El firmware: UEFI y BIOS
  3. GRUB 2: el gestor de arranque
  4. El initramfs: el sistema mínimo intermedio
  5. El kernel y el paso de control a PID 1
  6. systemd y los targets
  7. Parámetros de la línea de comandos del kernel
  8. Recuperación: intervenir en el arranque
  9. Recuperar un sistema que no arranca
  10. Reinstalar GRUB desde un medio de rescate

La cadena de arranque completa

Arrancar un sistema es una sucesión de programas, cada uno con más capacidad que el anterior, en la que cada eslabón carga y cede el control al siguiente. Se llama bootstrapping precisamente por eso.

graph TD
    A["Firmware UEFI<br/>(en la placa)"] -->|lee la ESP| B["GRUB 2<br/>shimx64.efi → grubx64.efi"]
    B -->|carga en RAM| C["vmlinuz<br/>(kernel comprimido)"]
    B -->|carga en RAM| D["initrd.img<br/>(initramfs)"]
    C -->|se descomprime<br/>e inicializa| E["Kernel<br/>drivers, memoria, planificador"]
    D -->|raiz temporal| E
    E -->|monta la raiz real<br/>y hace switch_root| F["systemd<br/>PID 1"]
    F -->|activa dependencias| G["default.target<br/>= multi-user.target"]
    G --> H["getty, sshd,<br/>tramontana.service"]

Los cinco eslabones y su responsabilidad, que conviene tener en la cabeza porque el diagnóstico consiste en identificar en cuál se rompió:

Eslabón Qué hace Cómo sabes que llegó aquí
Firmware Inicializa el hardware, encuentra el gestor de arranque Aparece el logotipo de la placa o la pantalla de la BIOS
GRUB Encuentra el kernel, lo carga en memoria, le pasa parámetros Aparece el menú (o la pantalla se queda en negro con GRUB en modo rescate)
Kernel Inicializa el hardware de verdad, monta la raíz Empiezan los mensajes de dmesg por pantalla
initramfs Aporta los drivers y utilidades para poder montar la raíz Un fallo aquí da el prompt (initramfs)
systemd Arranca los servicios en el orden correcto Aparecen las líneas [ OK ] Started ...

Esa tabla es la herramienta de diagnóstico más útil de la lección: cuando alguien te diga «el servidor no arranca», la primera pregunta es hasta dónde llegó.

El firmware: UEFI y BIOS

El firmware vive en la placa base, se ejecuta antes que cualquier cosa que esté en el disco, y su trabajo es dejar el hardware en un estado usable y localizar algo que arrancar. Hay dos generaciones, y srv-tramontana usa la moderna:

BIOS + MBR UEFI + GPT
Antigüedad Desde 1981 Desde 2005, universal desde 2012
Dónde busca el arranque Los primeros 446 bytes del disco (MBR) Ficheros .efi en la partición ESP
Tamaño del cargador inicial 446 bytes: obliga a un arranque en dos fases Un ejecutable completo, sin límite práctico
Tabla de particiones MBR: 4 primarias, 2 TiB máximo GPT: 128 particiones, 8 ZiB
Sistema de ficheros que entiende Ninguno FAT32
Arranque seguro No Secure Boot: firma criptográfica del cargador
Gestión de entradas No hay Variables NVRAM, gestionables con efibootmgr

La diferencia clave es la tercera fila. En BIOS, el cargador tenía que caber en 446 bytes, lo que obligaba a un salto en dos fases y a colocar código en el espacio entre el MBR y la primera partición. En UEFI, el firmware sabe leer FAT32, así que el cargador es un fichero normal en una partición normal.

Esa partición es la ESP (EFI System Partition):

$ lsblk -f /dev/sda
NAME   FSTYPE FSVER LABEL  UUID                                 MOUNTPOINTS
sda
├─sda1 vfat   FAT32        A1B2-C3D4                            /boot/efi
├─sda2 ext4   1.0          7c4e1f92-3a8b-4d15-9e26-8f3a0b7c1d54 /boot
└─sda3 ext4   1.0          3f8a2c19-6b4d-4e71-a835-1c9e5f2d0a87 /

$ ls /boot/efi/EFI/
BOOT  ubuntu

$ ls -l /boot/efi/EFI/ubuntu/
-rwx------ 1 root root  126976 ago 18 09:14 grubx64.efi
-rwx------ 1 root root     108 ago 18 09:14 grub.cfg
-rwx------ 1 root root  955512 ago 18 09:14 shimx64.efi
-rwx------ 1 root root 1224264 ago 18 09:14 mmx64.efi

Tres ficheros que conviene distinguir, porque el orden en que se llaman importa cuando algo falla:

  • shimx64.efi es el primer eslabón cuando Secure Boot está activo: está firmado por Microsoft (cuya clave viene de fábrica en las placas), y su única función es verificar y cargar el siguiente. Es el puente entre la cadena de confianza del fabricante y la de la distribución.
  • grubx64.efi es GRUB propiamente dicho, firmado por Canonical.
  • mmx64.efi (MokManager) gestiona las claves propias, y es lo que permite firmar un módulo de kernel propio (relevante con DKMS, que verás en 07-03).

Las entradas de arranque no están en el disco, sino en la NVRAM de la placa, y se gestionan con efibootmgr:

$ sudo efibootmgr -v
BootCurrent: 0000
Timeout: 3 seconds
BootOrder: 0000,0001
Boot0000* ubuntu  HD(1,GPT,a1b2c3d4-...,0x800,0x100000)/File(\EFI\ubuntu\shimx64.efi)
Boot0001* UEFI VBOX HARDDISK  PciRoot(0x0)/Pci(0x1,0x1)/Ata(0,0,0)

BootOrder es el orden en que el firmware prueba las entradas. Poder reordenarlo o crear una entrada nueva desde el sistema en marcha es lo que salva la situación cuando otro sistema operativo, o una actualización de firmware, ha dejado tu entrada al final o la ha borrado:

# Crear una entrada nueva apuntando al cargador de Ubuntu
$ sudo efibootmgr -c -d /dev/sda -p 1 -L "Ubuntu Tramontana" -l '\EFI\ubuntu\shimx64.efi'

# Poner esa entrada primera
$ sudo efibootmgr -o 0002,0000,0001

Una advertencia real: efibootmgr escribe en la NVRAM de la placa, y en algunos equipos —sobre todo portátiles de consumo— un uso incorrecto ha llegado a dejar la placa inservible. En una VM es completamente inocuo, y ahí es donde debes practicar.

GRUB 2: el gestor de arranque

GRUB (GRand Unified Bootloader) resuelve un problema que el firmware no puede: saber leer sistemas de ficheros Linux, entender LVM y RAID, presentar un menú, y cargar un kernel con los parámetros adecuados.

Los ficheros, y el que nunca se edita

$ ls /boot/grub/
fonts  gfxblacklist.txt  grub.cfg  grubenv  i386-pc  locale  unicode.pf2  x86_64-efi
$ head -6 /boot/grub/grub.cfg
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

El aviso es literal y hay que tomárselo así: grub.cfg se genera, y cualquier cambio manual desaparece en la siguiente actualización del kernel, que ejecuta update-grub como parte de su script de mantenedor. Las dos fuentes reales son:

  • /etc/default/grub: los ajustes en formato clave-valor.
  • /etc/grub.d/: los scripts que generan cada sección del menú.
$ cat /etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX=""
GRUB_DISABLE_OS_PROBER=false

Las directivas que de verdad se tocan en un servidor:

Directiva Qué hace Valor sensato en un servidor
GRUB_TIMEOUT Segundos de espera en el menú 5: suficiente para intervenir, no tanto como para molestar
GRUB_TIMEOUT_STYLE menu, hidden o countdown menu: oculto no sirve si no puedes verlo para intervenir
GRUB_DEFAULT Entrada por defecto 0, o saved con GRUB_SAVEDEFAULT=true
GRUB_CMDLINE_LINUX_DEFAULT Parámetros del kernel en el arranque normal Ver el apartado de parámetros
GRUB_CMDLINE_LINUX Parámetros en todas las entradas, incluida recuperación Solo lo imprescindible
GRUB_DISABLE_RECOVERY Oculta las entradas de recuperación false: son las que te salvan
GRUB_ENABLE_BLSCFG Formato BootLoaderSpec (RHEL) No aplica en Ubuntu

Y la regla operativa, con la convención del curso:

$ sudo cp -p /etc/default/grub /etc/default/grub.bak-$(date +%F)
$ sudo sed -i 's/^GRUB_TIMEOUT=5$/GRUB_TIMEOUT=10/' /etc/default/grub
$ sudo diff -u /etc/default/grub.bak-$(date +%F) /etc/default/grub
--- /etc/default/grub.bak-2026-08-18
+++ /etc/default/grub
@@ -3,7 +3,7 @@
-GRUB_TIMEOUT=5
+GRUB_TIMEOUT=10

$ sudo update-grub
Sourcing file `/etc/default/grub'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.8.0-41-generic
Found initrd image: /boot/initrd.img-6.8.0-41-generic
Found linux image: /boot/vmlinuz-6.8.0-39-generic
Found initrd image: /boot/initrd.img-6.8.0-39-generic
done

Fíjate en que encuentra dos kernels. Eso no es casual y es una red de seguridad importante: si una actualización de kernel rompe algo —un driver que desaparece, un módulo de terceros incompatible—, el menú de GRUB te ofrece el anterior. La configuración que lo garantiza:

$ apt-mark showmanual | grep -c linux-generic
1
$ ls /boot/vmlinuz-*
/boot/vmlinuz-6.8.0-39-generic  /boot/vmlinuz-6.8.0-41-generic

Ubuntu conserva por defecto los kernels necesarios y apt autoremove limpia los antiguos. El error a evitar es borrarlos a mano para liberar espacio en /boot cuando se llena: si te quedas con uno solo y ese falla, no hay a dónde volver. La solución correcta cuando /boot se llena es sudo apt autoremove --purge, que respeta el kernel en uso y el anterior.

La estructura del menú

$ ls /etc/grub.d/
00_header  05_debian_theme  10_linux  20_linux_xen  30_os-prober  40_custom  41_custom

Los scripts se ejecutan en orden numérico y cada uno aporta su parte al grub.cfg. 10_linux genera las entradas de los kernels instalados, 30_os-prober detecta otros sistemas operativos, y 40_custom es donde se ponen entradas propias — porque es el único que no se regenera.

Para consultar el menú actual sin reiniciar:

$ awk -F"'" '/^menuentry / {print NR": "$2}' /boot/grub/grub.cfg
6: Ubuntu
$ awk -F"'" '/^\s*menuentry / {print "   - "$2}' /boot/grub/grub.cfg
   - Ubuntu, with Linux 6.8.0-41-generic
   - Ubuntu, with Linux 6.8.0-41-generic (recovery mode)
   - Ubuntu, with Linux 6.8.0-39-generic
   - Ubuntu, with Linux 6.8.0-39-generic (recovery mode)

El initramfs: el sistema mínimo intermedio

Este es el eslabón que menos se entiende y el que más problemas causa. El problema que resuelve es un círculo vicioso:

Para montar el sistema de ficheros raíz, el kernel necesita el driver del controlador de disco, el módulo del sistema de ficheros, y —en srv-tramontana— los módulos de LVM y de LUKS, más las utilidades lvm y cryptsetup. Pero todo eso está dentro del sistema de ficheros raíz que aún no puede montar.

El initramfs rompe el círculo: es un archivo comprimido con un sistema de ficheros mínimo que GRUB carga en memoria junto al kernel. El kernel lo monta como raíz temporal, ejecuta su script de arranque, que carga los módulos, desbloquea LUKS, activa los volúmenes LVM y monta la raíz real; y entonces hace switch_root para cambiar a ella y ejecutar el systemd de verdad.

$ ls -lh /boot/initrd.img-*
-rw-r--r-- 1 root root 74M ago 18 09:14 /boot/initrd.img-6.8.0-41-generic
-rw-r--r-- 1 root root 74M jul 22 11:02 /boot/initrd.img-6.8.0-39-generic

# Que hay dentro: cryptsetup y lvm son los que importan aqui
$ lsinitramfs /boot/initrd.img-6.8.0-41-generic | grep -E 'cryptsetup$|/lvm$|sd_mod|ext4'
usr/lib/x86_64-linux-gnu/libcryptsetup.so.12
usr/sbin/cryptsetup
usr/sbin/lvm
usr/lib/modules/6.8.0-41-generic/kernel/drivers/scsi/sd_mod.ko.zst
usr/lib/modules/6.8.0-41-generic/kernel/fs/ext4/ext4.ko.zst

$ lsinitramfs /boot/initrd.img-6.8.0-41-generic | wc -l
4127

Que cryptsetup y lvm estén ahí no es automático: los scripts de initramfs-tools los incluyen porque leen /etc/crypttab y /etc/fstab en el momento de generar el initramfs. Y de ahí sale la regla operativa más importante de este apartado:

Después de tocar /etc/crypttab, la configuración de LVM o el esquema de discos de arranque, hay que regenerar el initramfs. Si no, el sistema arrancará con un initramfs que no sabe nada del cambio y se quedará en el prompt (initramfs).

$ sudo update-initramfs -u              # el kernel actual
$ sudo update-initramfs -u -k all       # todos los kernels instalados
update-initramfs: Generating /boot/initrd.img-6.8.0-41-generic
update-initramfs: Generating /boot/initrd.img-6.8.0-39-generic

El -k all es el que salva: si solo regeneras el actual y luego necesitas arrancar con el anterior, te encuentras el mismo fallo desde el otro kernel.

La configuración vive en /etc/initramfs-tools/:

$ grep -v '^#' /etc/initramfs-tools/initramfs.conf | grep -v '^$'
MODULES=most
BUSYBOX=auto
COMPRESS=zstd
DEVICE=
NFSROOT=auto
RUNSIZE=10%

MODULES=most incluye una selección amplia de drivers; MODULES=dep incluye solo los que la máquina actual necesita, y produce un initramfs mucho más pequeño — a cambio de que deje de arrancar si mueves el disco a otro hardware. En un servidor virtual estable puede tener sentido; como valor por defecto, most es la elección prudente.

El kernel y el paso de control a PID 1

Cuando GRUB carga vmlinuz, este se descomprime y toma el control del hardware de verdad: detecta CPU y memoria, inicializa el planificador, monta /proc y /sys, carga los drivers integrados y ejecuta el initramfs.

Los parámetros con los que se arrancó quedan registrados y son consultables:

$ cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-6.8.0-41-generic root=UUID=3f8a2c19-6b4d-4e71-a835-1c9e5f2d0a87 ro quiet splash

Ese fichero es la primera cosa que hay que mirar cuando el arranque se comporta de forma inesperada: dice con qué se arrancó realmente, no con qué crees que se arrancó. Un single, un nomodeset o un init= olvidado en GRUB_CMDLINE_LINUX aparecen aquí.

Y dmesg es el diario del kernel durante el arranque:

$ sudo dmesg | head -3
[    0.000000] Linux version 6.8.0-41-generic (buildd@lcy02-amd64-045) ...
[    0.000000] Command line: BOOT_IMAGE=/vmlinuz-6.8.0-41-generic root=UUID=3f8a...
[    0.000000] KERNEL supported cpus: Intel AMD Hygon Centaur zhaoxin

# Errores y avisos del arranque actual
$ sudo journalctl -k -b -p warning --no-pager | head -5

# Y del arranque ANTERIOR: lo que necesitas cuando el sistema se cayo y volvio
$ sudo journalctl -k -b -1 -p err --no-pager

Poder consultar el arranque anterior es exactamente la razón por la que en 05-06 hiciste persistente el journal. Sin /var/log/journal, -b -1 no existe y el diagnóstico de un arranque fallido se pierde al reiniciar.

Al final de su inicialización, el kernel ejecuta el proceso init —hoy /sbin/init, que es un enlace a systemd— y le entrega el control como PID 1. Desde ese momento el kernel solo atiende llamadas al sistema; el arranque lo dirige el espacio de usuario.

systemd y los targets

Ya conoces systemd desde 05-05: unidades, dependencias, timers. Lo que añade esta lección es su papel como director del arranque.

systemd activa default.target y, hacia atrás, todo lo que este necesita:

$ systemctl get-default
multi-user.target

$ systemctl list-dependencies default.target | head -12
default.target
● ├─tramontana.service
● ├─cron.service
● ├─fail2ban.service
● ├─ssh.service
● ├─basic.target
● │ ├─sysinit.target
● │ │ ├─systemd-journald.service
● │ │ ├─cryptsetup.target
● │ │ └─local-fs.target
● │ └─sockets.target
● └─timers.target

Los targets que hay que conocer, porque son los que se usan en recuperación:

Target Qué activa Para qué sirve
emergency.target Solo una shell; la raíz montada en solo lectura, sin /usr El último recurso; fstab roto
rescue.target Shell + sistemas de ficheros locales montados Arreglar la mayoría de problemas
multi-user.target Todo, sin entorno gráfico El estado normal de un servidor
graphical.target multi-user + gestor de sesiones Escritorio

Y las dos herramientas de análisis del arranque:

$ systemd-analyze
Startup finished in 3.412s (kernel) + 8.847s (userspace) = 12.259s
multi-user.target reached after 8.712s in userspace.

$ systemd-analyze blame | head -6
4.218s [email protected]
2.104s snapd.service
1.882s cryptsetup@backups\x2dcifrado.service
 947ms tramontana.service
 612ms systemd-udev-settle.service
 388ms fail2ban.service

$ systemd-analyze critical-chain
multi-user.target @8.712s
└─tramontana.service @7.765s +947ms
  └─postgresql.service @7.762s
    └─network-online.target @3.541s
      └─systemd-networkd-wait-online.service @1.104s +2.437s

La diferencia entre las dos es conceptual y decide dónde optimizar: blame ordena por tiempo que tardó cada unidad, y critical-chain muestra la cadena de dependencias que determina el tiempo total. snapd.service tarda 2 segundos, pero no está en la cadena crítica: arranca en paralelo y no retrasa nada. En cambio systemd-networkd-wait-online sí, y ahí sí merece la pena investigar.

Parámetros de la línea de comandos del kernel

Los parámetros que GRUB pasa al kernel son la palanca de intervención en el arranque. Los que hay que conocer:

Parámetro Efecto Cuándo se usa
ro / rw Monta la raíz en solo lectura / lectura-escritura rw con init=/bin/bash
quiet Silencia los mensajes del kernel Quítalo para ver dónde falla
splash Pantalla gráfica de arranque Quítalo por lo mismo
single o 1 Arranca en rescue.target Modo mantenimiento
systemd.unit=<target> Arranca en el target indicado emergency.target, rescue.target
init=/bin/bash Sustituye PID 1 por una shell Contraseña de root perdida; systemd no arranca
systemd.mask=<unidad> Enmascara una unidad solo en este arranque Un servicio que cuelga el arranque
nomodeset Desactiva los drivers gráficos del kernel Pantalla en negro por vídeo
noapic / acpi=off Desactiva gestión de interrupciones / energía Bloqueos por firmware
emergency Equivale a systemd.unit=emergency.target Último recurso
debug systemd.log_level=debug Registro exhaustivo Diagnóstico fino del arranque

El primer consejo práctico de recuperación es el más simple: quitar quiet splash. La pantalla de arranque bonita oculta precisamente los mensajes que te dirían dónde se rompió.

Recuperación: intervenir en el arranque

Editar la entrada del menú

En el menú de GRUB, con la entrada seleccionada, la tecla e abre el editor. Es un editor efímero: los cambios afectan solo a este arranque y no tocan nada del disco. Es la propiedad que lo hace seguro para experimentar.

El procedimiento:

  1. Enciende la VM y, si el menú no aparece, mantén pulsada Shift (BIOS) o pulsa Esc repetidamente (UEFI).
  2. Selecciona la entrada de Ubuntu y pulsa e.
  3. Localiza la línea que empieza por linux /vmlinuz-....
  4. Modifica lo que necesites al final de esa línea.
  5. Ctrl+X o F10 para arrancar con esos parámetros.

La línea original y las tres variantes más útiles:

# Original
linux /vmlinuz-6.8.0-41-generic root=UUID=3f8a2c19-... ro quiet splash

# Ver que pasa de verdad
linux /vmlinuz-6.8.0-41-generic root=UUID=3f8a2c19-... ro

# Arrancar en modo rescate (shill de root, sistemas de ficheros montados)
linux /vmlinuz-6.8.0-41-generic root=UUID=3f8a2c19-... ro systemd.unit=rescue.target

# Saltarse systemd por completo: una shell como PID 1
linux /vmlinuz-6.8.0-41-generic root=UUID=3f8a2c19-... rw init=/bin/bash

rescue frente a emergency

rescue.target emergency.target
Sistemas de ficheros locales Montados (local-fs.target) Solo la raíz, en solo lectura
/usr, /var en particiones aparte Montados No montados
Servicios Ninguno más allá de lo básico Ninguno
Red No No
Requiere contraseña de root Sí Sí
Cuándo usarlo Casi siempre Cuando rescue tampoco arranca

rescue es el que se usa el 90 % de las veces: tienes los sistemas de ficheros montados y las herramientas disponibles. emergency es para cuando el problema está en el propio montaje —un fstab roto es el caso típico—, y ahí lo primero es hacer escribible la raíz:

# En emergency.target, la raiz esta en solo lectura
root@srv-tramontana:~# mount -o remount,rw /
root@srv-tramontana:~# nano /etc/fstab

init=/bin/bash y la raíz en solo lectura

init=/bin/bash es el recurso más potente: sustituye PID 1 por una shell, así que systemd no llega a ejecutarse. Sirve cuando el problema está en systemd o en la propia autenticación.

Y tiene dos peculiaridades que desconciertan la primera vez:

bash-5.2# whoami
bash: whoami: command not found

El PATH no está configurado, porque no ha corrido ningún script de inicio. Se arregla a mano:

bash-5.2# export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
bash-5.2# mount | head -1
/dev/mapper/... on / type ext4 (ro,relatime)

Y la raíz está en solo lectura, porque el parámetro ro sigue vigente y nadie la ha remontado:

bash-5.2# mount -o remount,rw /
bash-5.2# touch /prueba && echo "ya se puede escribir"
ya se puede escribir

Al terminar, y esto es importante: no reinicies con reboot, porque no hay systemd para atender la petición y los datos pueden quedar sin sincronizar. La secuencia correcta:

bash-5.2# sync
bash-5.2# mount -o remount,ro /
bash-5.2# exec /sbin/init      # arrancar systemd desde aqui
# o, si prefieres reiniciar:
bash-5.2# echo b > /proc/sysrq-trigger

Recuperar la contraseña de root

Un escenario clásico, y una demostración incómoda de por qué el acceso físico —o a la consola del hipervisor— equivale al control del sistema:

# 1. Menu de GRUB → e → anadir al final de la linea linux:
#    (cambiar 'ro' por 'rw')
#    rw init=/bin/bash
# 2. Ctrl+X

bash-5.2# export PATH=/usr/sbin:/usr/bin:/sbin:/bin
bash-5.2# mount -o remount,rw /
bash-5.2# passwd root
New password:
Retype new password:
passwd: password updated successfully

# 3. Si hay SELinux (RHEL), hay que reetiquetar; en Ubuntu con AppArmor no hace falta
bash-5.2# sync
bash-5.2# exec /sbin/init

La lección de seguridad que hay que extraer: cualquiera con acceso a la consola de la máquina puede hacer esto en dos minutos. Las contramedidas —contraseña en GRUB con grub-mkpasswd-pbkdf2, cifrado completo del disco con LUKS incluyendo /boot, Secure Boot, y control de acceso físico— son precisamente las que en el modelo de amenazas de 06-06 quedaron fuera de alcance. Ahora entiendes por qué esa decisión tenía que ser explícita.

Recuperar un sistema que no arranca

El escenario que 05-04 anunció: fstab roto

Vas a provocarlo a propósito, porque es el fallo más común tras un cambio de discos y porque en 06-05 modificaste fstab para el volumen LUKS.

# Provocar el fallo: un UUID que no existe, sin nofail
$ sudo cp -p /etc/fstab /etc/fstab.bak-$(date +%F)
$ echo 'UUID=00000000-0000-0000-0000-000000000000 /datos ext4 defaults 0 2' \
    | sudo tee -a /etc/fstab
$ sudo mkdir -p /datos
$ sudo reboot

Al arrancar, en lugar del prompt de inicio de sesión aparece:

[  FAILED ] Failed to mount /datos.
[DEPEND] Dependency failed for Local File Systems.
You are in emergency mode. After logging in, type "journalctl -xb" to view
system logs, ...
Press Enter for maintenance
(or press Control-D to continue):

Esto es exactamente lo que mount -a habría evitado. El diagnóstico y la reparación:

# 1. Entrar en mantenimiento con la contrasena de root
Give root password for maintenance:

# 2. Confirmar la causa
root@srv-tramontana:~# systemctl --failed --no-pager
  UNIT           LOAD   ACTIVE SUB    DESCRIPTION
● datos.mount    loaded failed failed /datos
● local-fs.target loaded failed failed Local File Systems

root@srv-tramontana:~# journalctl -xb -u datos.mount --no-pager | tail -3
mount: /datos: can't find UUID=00000000-0000-0000-0000-000000000000.

# 3. Hacer escribible la raiz y arreglar
root@srv-tramontana:~# mount -o remount,rw /
root@srv-tramontana:~# nano /etc/fstab      # comentar o corregir la linea

# 4. VERIFICAR antes de reiniciar: la misma red de seguridad de 05-04
root@srv-tramontana:~# systemctl daemon-reload
root@srv-tramontana:~# mount -a && echo "fstab correcto"
fstab correcto

# 5. Continuar el arranque sin reiniciar
root@srv-tramontana:~# systemctl default

Y las dos lecciones, que hay que anotar en el runbook:

  1. mount -a antes de reiniciar, siempre. Es una comprobación de dos segundos que evita esta situación.
  2. nofail en todo montaje que no sea imprescindible para arrancar. Con nofail, un dispositivo ausente produce un aviso en el journal y el sistema arranca. Es exactamente por eso que la línea del volumen de copias lo lleva:
/dev/mapper/backups-cifrado  /srv/tramontana/backups  ext4  defaults,noatime,nodev,nosuid,nofail  0  2

El prompt (initramfs)

Un fallo distinto y más profundo: el initramfs no ha conseguido montar la raíz.

Gave up waiting for root file system device.
ALERT!  UUID=3f8a2c19-... does not exist.  Dropping to a shell!

BusyBox v1.36.1 (Ubuntu 1:1.36.1-6ubuntu3) built-in shell (ash)

(initramfs)

Las causas, con su comprobación:

# 1. Ver que dispositivos detecta el kernel: el problema es que falta el driver?
(initramfs) cat /proc/partitions
(initramfs) ls /dev/sd* /dev/nvme* 2>/dev/null

# 2. Si el disco esta pero es LVM: activar los volumenes a mano
(initramfs) lvm vgscan
(initramfs) lvm vgchange -ay
(initramfs) ls /dev/mapper/

# 3. Si es LUKS: desbloquear a mano
(initramfs) cryptsetup luksOpen /dev/sda3 raiz-cifrada
(initramfs) lvm vgchange -ay

# 4. Si se puede montar a mano, el problema es de configuracion, no de hardware
(initramfs) mkdir /raiz && mount /dev/mapper/vg-root /raiz && ls /raiz
(initramfs) exit      # BusyBox intenta continuar el arranque

Si el paso 4 funciona, sabes que el disco y el sistema de ficheros están bien y que lo que falta está en el initramfs o en crypttab. Se arranca con el kernel anterior desde el menú de GRUB —cuyo initramfs es el de antes del cambio— y se regenera:

$ sudo update-initramfs -u -k all

Es la razón por la que conservar dos kernels es una medida de recuperación, no un desperdicio de espacio.

Reinstalar GRUB desde un medio de rescate

El escenario más grave: GRUB no aparece en absoluto. El firmware no encuentra nada que arrancar, o arranca directamente otro sistema. Ocurre tras instalar otro sistema operativo, tras clonar un disco, o tras una actualización de firmware que borró la entrada de la NVRAM.

Se resuelve arrancando desde un medio externo (el ISO de Ubuntu en modo Try Ubuntu), montando el sistema instalado y entrando en él con chroot — que es la operación conceptualmente interesante de esta lección, porque es la misma primitiva sobre la que se construyen los contenedores de 07-05.

# 1. Identificar las particiones
ubuntu@ubuntu:~$ lsblk -f
NAME   FSTYPE FSVER LABEL  UUID                                 MOUNTPOINTS
sda
├─sda1 vfat   FAT32        A1B2-C3D4
├─sda2 ext4   1.0          7c4e1f92-3a8b-4d15-9e26-8f3a0b7c1d54
└─sda3 ext4   1.0          3f8a2c19-6b4d-4e71-a835-1c9e5f2d0a87

# 2. Montar la raiz, y despues /boot y la ESP DENTRO de ella
ubuntu@ubuntu:~$ sudo mount /dev/sda3 /mnt
ubuntu@ubuntu:~$ sudo mount /dev/sda2 /mnt/boot
ubuntu@ubuntu:~$ sudo mount /dev/sda1 /mnt/boot/efi

# 3. Los cuatro montajes bind imprescindibles.
#    /dev  -> acceso a los dispositivos reales
#    /proc -> informacion de procesos y kernel
#    /sys  -> interfaz del kernel
#    /sys/firmware/efi/efivars -> ESCRIBIR en la NVRAM (sin esto,
#                                 grub-install falla en UEFI)
ubuntu@ubuntu:~$ for d in /dev /dev/pts /proc /sys /sys/firmware/efi/efivars /run; do
                     sudo mount --bind "$d" "/mnt$d"
                 done

# 4. Entrar en el sistema instalado
ubuntu@ubuntu:~$ sudo chroot /mnt /bin/bash
root@ubuntu:/#

Ese cuarto montaje es el que hace fracasar la mitad de los intentos de reparación de GRUB en UEFI: sin efivars accesible en escritura, grub-install no puede crear la entrada de arranque y aborta con un error que no explica la causa.

# 5. Reinstalar GRUB y regenerar la configuracion
root@ubuntu:/# grub-install --target=x86_64-efi --efi-directory=/boot/efi \
                   --bootloader-id=ubuntu --recheck
Installing for x86_64-efi platform.
Installation finished. No error reported.

root@ubuntu:/# update-grub
root@ubuntu:/# update-initramfs -u -k all

# 6. Comprobar que la entrada existe en la NVRAM
root@ubuntu:/# efibootmgr -v | grep -i ubuntu
Boot0000* ubuntu  HD(1,GPT,...)/File(\EFI\ubuntu\shimx64.efi)

# 7. Salir limpiamente: desmontar en ORDEN INVERSO
root@ubuntu:/# exit
ubuntu@ubuntu:~$ for d in /run /sys/firmware/efi/efivars /sys /proc /dev/pts /dev; do
                     sudo umount "/mnt$d"
                 done
ubuntu@ubuntu:~$ sudo umount /mnt/boot/efi /mnt/boot /mnt
ubuntu@ubuntu:~$ sudo reboot

El orden inverso al desmontar no es una formalidad: desmontar /mnt antes de /mnt/dev falla con target is busy, y forzarlo puede dejar el sistema de ficheros marcado como sucio.

Para un sistema con BIOS/MBR en lugar de UEFI, el paso 5 cambia y los montajes de efivars no aplican:

root@ubuntu:/# grub-install /dev/sda      # el DISCO, no la particion

Errores Comunes y Consejos

  • Editar /boot/grub/grub.cfg a mano. El fichero lo dice en la tercera línea. Los cambios desaparecen en la siguiente actualización de kernel. Se edita /etc/default/grub y se ejecuta update-grub.
  • Olvidar update-grub o update-initramfs tras un cambio. Editar /etc/default/grub sin update-grub no hace nada. Tocar crypttab o LVM sin update-initramfs -u -k all produce el prompt (initramfs) en el siguiente arranque.
  • Regenerar el initramfs solo del kernel actual. Si luego necesitas arrancar con el anterior, te encuentras el mismo fallo. Siempre -k all.
  • Borrar kernels antiguos a mano para liberar /boot. Quedarte con uno solo elimina tu red de seguridad. Usa apt autoremove --purge, que respeta el kernel en uso y el anterior.
  • Montajes sin nofail en fstab. Un dispositivo ausente impide arrancar. Solo la raíz y /boot deben poder bloquear el arranque.
  • No ejecutar mount -a antes de reiniciar. Es la comprobación de dos segundos que separa un aviso de una sesión en modo emergencia con la consola del hipervisor.
  • GRUB_TIMEOUT_STYLE=hidden en un servidor. Un menú oculto no se puede usar para intervenir. Y GRUB_TIMEOUT=0 es peor: elimina la posibilidad de recuperación por menú.
  • Dejar quiet splash al diagnosticar. Quítalos: los mensajes que ocultan son exactamente los que dicen dónde falla.
  • Olvidar --bind /sys/firmware/efi/efivars en el chroot. grub-install falla en UEFI con un error poco descriptivo. Es la causa más común de reparaciones fallidas.
  • Reiniciar con reboot desde init=/bin/bash. No hay systemd que atienda la petición. sync, remontar en solo lectura, y exec /sbin/init o echo b > /proc/sysrq-trigger.
  • Consejo de método. Practica los tres procedimientos —fstab roto, contraseña de root, reinstalar GRUB— en el laboratorio y con snapshot previo, hoy, con calma. La primera vez que los necesites será a las 3 de la madrugada con un servicio caído, y ese no es momento de aprender.

Ejercicios

Ejercicio 1

Provoca deliberadamente el prompt (initramfs) en tu laboratorio y recupéralo. Parte de que /srv/tramontana/backups está cifrado con LUKS y su clave se declara en /etc/crypttab. Describe el cambio que provoca el fallo, por qué el sistema no arranca, cómo lo diagnosticas desde el prompt de BusyBox, y las dos formas de recuperarlo.

Ejercicio 2

El arranque de srv-tramontana tarda 47 segundos, cuando antes tardaba 12. Describe el procedimiento de diagnóstico usando las herramientas de systemd, explicando qué información aporta cada una y cómo distingues una unidad lenta que no importa de una que sí.

Ejercicio 3

Marta te pide un procedimiento escrito de recuperación de arranque para el runbook, que pueda seguir alguien que no seas tú. Redáctalo como un árbol de decisión: qué observar, qué preguntarse y qué hacer en cada rama, cubriendo los cuatro escenarios que has visto en la lección.

Soluciones

Solución 1

Provocar el fallo. El escenario realista es un cambio en crypttab sin regenerar el initramfs. Como el volumen cifrado es el de copias y lleva nofail, para que el fallo sea de arranque hay que tocar algo que sí bloquea. La forma limpia de reproducirlo es eliminar los módulos de LUKS y LVM del initramfs:

$ sudo cp -p /etc/initramfs-tools/initramfs.conf{,.bak-$(date +%F)}
$ sudo cp -p /etc/crypttab /etc/crypttab.bak-$(date +%F)

# Vaciar crypttab: initramfs-tools lo lee para decidir si incluye cryptsetup
$ sudo truncate -s 0 /etc/crypttab
$ sudo sed -i 's/^MODULES=most/MODULES=dep/' /etc/initramfs-tools/initramfs.conf
$ sudo update-initramfs -u -k all
$ lsinitramfs /boot/initrd.img-$(uname -r) | grep -c cryptsetup
0
$ sudo reboot

Por qué no arranca. El initramfs es el único entorno que existe antes de montar la raíz, y su script de arranque necesita cryptsetup para desbloquear el volumen LUKS y lvm para activar los volúmenes lógicos. Al no estar incluidos —porque crypttab estaba vacío cuando se generó—, el script no encuentra el dispositivo raíz, espera el tiempo máximo y cae a la shell de BusyBox. Es el círculo vicioso del apartado del initramfs en su forma más pura: las herramientas para montar la raíz están dentro de la raíz que no se puede montar.

Diagnóstico desde BusyBox. Descartando de fuera hacia dentro:

# 1. Ve el kernel el disco fisico? Si no, falta un DRIVER
(initramfs) cat /proc/partitions
major minor  #blocks  name
   8        0   26214400 sda
   8        1     524288 sda1
   8        2     976562 sda2
   8        3   24712550 sda3

El disco y sus tres particiones están. Descartado el driver.

# 2. Estan las herramientas que hacen falta?
(initramfs) which cryptsetup lvm
(initramfs)

Sin salida: ahí está la causa. Ninguna de las dos está en el initramfs.

# 3. Confirmar que el sistema de ficheros esta sano montandolo a mano
(initramfs) blkid /dev/sda3
/dev/sda3: UUID="3f8a2c19-..." TYPE="ext4"
(initramfs) mkdir /raiz && mount -o ro /dev/sda3 /raiz
(initramfs) ls /raiz
bin boot dev etc home lib opt proc root run sbin srv sys tmp usr var

El sistema está intacto. El problema es exclusivamente del initramfs, que es la conclusión que orienta la reparación.

Las dos formas de recuperarlo.

Forma A — arrancar con el kernel anterior (la rápida). El initramfs del kernel 6.8.0-39 se generó antes del cambio, así que sigue completo... salvo que hayas usado -k all, que es exactamente lo que hicimos. Si el update-initramfs hubiera sido solo del actual, esta sería la salida en treinta segundos: menú de GRUB → Advanced options → kernel 6.8.0-39 → arranca → regenerar. La lección es doble: -k all es lo correcto para no dejar un kernel roto, pero significa que un error de configuración afecta a todos los kernels a la vez. Por eso la comprobación (lsinitramfs | grep cryptsetup) va antes del reinicio, no después.

Forma B — chroot desde un medio de rescate (la que siempre funciona).

# Arrancar desde el ISO en modo Try Ubuntu
ubuntu@ubuntu:~$ sudo cryptsetup luksOpen /dev/sda3 raiz    # si la raiz esta cifrada
ubuntu@ubuntu:~$ sudo mount /dev/sda3 /mnt
ubuntu@ubuntu:~$ sudo mount /dev/sda2 /mnt/boot
ubuntu@ubuntu:~$ sudo mount /dev/sda1 /mnt/boot/efi
ubuntu@ubuntu:~$ for d in /dev /dev/pts /proc /sys /sys/firmware/efi/efivars /run; do
                     sudo mount --bind "$d" "/mnt$d"; done
ubuntu@ubuntu:~$ sudo chroot /mnt /bin/bash

# Restaurar la configuracion desde las copias .bak que SI hiciste
root@ubuntu:/# cp /etc/crypttab.bak-2026-08-18 /etc/crypttab
root@ubuntu:/# cp /etc/initramfs-tools/initramfs.conf.bak-2026-08-18 \
                  /etc/initramfs-tools/initramfs.conf
root@ubuntu:/# update-initramfs -u -k all

# VERIFICAR antes de reiniciar
root@ubuntu:/# lsinitramfs /boot/initrd.img-6.8.0-41-generic | grep -c 'sbin/cryptsetup'
1
root@ubuntu:/# lsinitramfs /boot/initrd.img-6.8.0-39-generic | grep -c 'sbin/cryptsetup'
1
root@ubuntu:/# exit
ubuntu@ubuntu:~$ for d in /run /sys/firmware/efi/efivars /sys /proc /dev/pts /dev; do
                     sudo umount "/mnt$d"; done
ubuntu@ubuntu:~$ sudo umount /mnt/boot/efi /mnt/boot /mnt && sudo reboot

Y las dos conclusiones que van al runbook: las copias .bak-$(date +%F) de la convención del curso son lo que hizo trivial la reparación —sin ellas habría que reconstruir la configuración de memoria—, y la verificación con lsinitramfs va antes del reinicio, no después. El patrón es idéntico al mount -a de fstab: comprobar en el sistema en marcha lo que solo se manifestaría al arrancar.

Solución 2

El procedimiento empieza por separar el arranque del kernel del arranque del espacio de usuario, porque son problemas distintos:

$ systemd-analyze
Startup finished in 3.398s (kernel) + 43.612s (userspace) = 47.010s
multi-user.target reached after 43.487s in userspace.

El kernel tarda lo mismo que siempre (3,4 s); los 35 segundos extra están en el espacio de usuario. Eso descarta hardware, drivers e initramfs, y centra la búsqueda en las unidades de systemd.

$ systemd-analyze blame | head -8
35.041s systemd-networkd-wait-online.service
 4.187s [email protected]
 2.098s snapd.service
 1.874s cryptsetup@backups\x2dcifrado.service
  938ms tramontana.service
  610ms systemd-udev-settle.service
  384ms fail2ban.service
  122ms apparmor.service

blame da el sospechoso, pero no basta, y aquí está el contenido del ejercicio: una unidad lenta solo importa si está en la cadena crítica. Hay que comprobarlo:

$ systemd-analyze critical-chain
The time when unit became active or started is printed after the "@" character.
The time the unit took to start is printed after the "+" character.

multi-user.target @43.487s
└─tramontana.service @42.540s +938ms
  └─postgresql.service @42.536s
    └─network-online.target @42.530s
      └─systemd-networkd-wait-online.service @7.489s +35.041s
        └─systemd-networkd.service @7.203s +281ms

Confirmado. systemd-networkd-wait-online está en la cadena, tarda 35 s, y arrastra todo lo que depende de la red: PostgreSQL espera a network-online.target, y tramontana.service espera a PostgreSQL. Los 35 s se propagan íntegros al total.

El contraste que pide el enunciado lo da snapd.service: tarda 2 segundos y no aparece en la cadena crítica, porque arranca en paralelo y nada lo espera. Optimizarlo no ahorraría ni una décima del tiempo total. Esa es la diferencia entre las dos herramientas:

Herramienta Qué responde Riesgo de malinterpretarla
systemd-analyze ¿Kernel o espacio de usuario? Ninguno; es el primer filtro
blame ¿Qué unidad tardó más? Alto: una unidad lenta en paralelo no retrasa nada
critical-chain ¿Qué determina el tiempo total? Bajo; es donde hay que optimizar
journalctl -b ¿Por qué tardó? Ninguno; es la causa raíz

La causa raíz, con el journal:

$ journalctl -b -u systemd-networkd-wait-online --no-pager
systemd-networkd-wait-online[701]: Timeout occurred while waiting for network connectivity.
systemd-networkd-wait-online[701]: Event loop failed: Connection timed out.

$ networkctl status enp0s3 | grep -E 'State|Online'
       State: routable (configured)
Online state: online

$ networkctl list
IDX LINK  TYPE     OPERATIONAL SETUP
  1 lo    loopback carrier     unmanaged
  2 enp0s3 ether   routable    configured
  3 virbr0 bridge  no-carrier  configured

Ahí está: virbr0, el puente de libvirt, está configured pero sin enlace, porque no hay ninguna máquina virtual arrancada conectada a él. systemd-networkd-wait-online espera por defecto a que todas las interfaces gestionadas estén en línea, y esa nunca lo estará. Los 35 segundos son su tiempo de espera máximo agotándose.

La corrección es decirle qué interfaz importa de verdad:

$ sudo mkdir -p /etc/systemd/system/systemd-networkd-wait-online.service.d
$ sudo tee /etc/systemd/system/systemd-networkd-wait-online.service.d/override.conf >/dev/null <<'EOF'
[Service]
ExecStart=
ExecStart=/usr/lib/systemd/systemd-networkd-wait-online --interface=enp0s3 --timeout=30
EOF
$ sudo systemctl daemon-reload

El ExecStart= vacío antes del nuevo es obligatorio: sin él, systemd añade un segundo comando en lugar de sustituir el primero, y la unidad falla. Es el mismo mecanismo de reseteo de lista que viste con SystemCallFilter en 06-06.

Y la verificación, con la disciplina de medir antes y después:

$ sudo reboot
# ... tras el reinicio
$ systemd-analyze
Startup finished in 3.402s (kernel) + 9.118s (userspace) = 12.520s
$ systemd-analyze critical-chain | head -5
multi-user.target @8.993s
└─tramontana.service @8.046s +938ms
  └─postgresql.service @8.041s
    └─network-online.target @8.034s
      └─systemd-networkd-wait-online.service @7.492s +541ms
$ ~/scripts/revision_salud.sh; echo "estado: $?"
estado: 0

De 47 s a 12,5 s, y el servicio verificado. Y una reflexión de método: el síntoma («el arranque tarda más») apareció después de instalar libvirt, y nadie relacionó las dos cosas. Anotar en el runbook el tiempo de arranque como parte de la línea base de 05-07 es lo que convierte «me parece que va más lento» en un dato con fecha.

Solución 3

RUNBOOK — Recuperación de arranque de srv-tramontana Versión 1.0 · 18 de agosto de 2026 · Autor: Operaciones de sistemas Este documento se guarda FUERA del servidor. Copia en el portátil de administración y en el gestor de contraseñas del equipo.

Requisitos previos. Acceso a la consola de la máquina en VirtualBox (no vale SSH: si no arranca, no hay red). Contraseña de root, disponible en pass tramontana/produccion/root. ISO de Ubuntu Server 24.04 accesible para el caso 4.


PASO 0 — La única pregunta que importa: ¿hasta dónde llegó?

Enciende la máquina y observa. No toques nada todavía. Anota la hora y lo que ves en pantalla.

Lo que ves Se rompió en Ve al caso
Pantalla negra, sin logotipo, sin menú Firmware o GRUB Caso 4
Menú de GRUB, pero no pasa de ahí GRUB o kernel Caso 4
Prompt (initramfs) initramfs Caso 3
Mensajes de arranque y luego emergency mode Montaje de sistemas de ficheros Caso 1
Arranca pero no puedes entrar Autenticación Caso 2
Arranca, pero muy lento Ninguno; es una unidad lenta Caso 5

CASO 1 — «You are in emergency mode» (lo más frecuente)

Casi siempre es /etc/fstab, tras un cambio de discos.

  1. Pulsa Enter e introduce la contraseña de root.
  2. Identifica qué falló: systemctl --failed
  3. Lee la causa: journalctl -xb | tail -30
  4. Haz escribible la raíz: mount -o remount,rw /
  5. Corrige /etc/fstab con nano. Si dudas, comenta la línea sospechosa anteponiendo #: es reversible y te devuelve el servicio.
  6. Verifica sin reiniciar: systemctl daemon-reload && mount -a
    • Sin errores → paso 7.
    • Con errores → vuelve al paso 5. No reinicies con mount -a fallando.
  7. Continúa el arranque: systemctl default
  8. Comprueba el servicio: /home/operador/scripts/revision_salud.sh (debe devolver 0).

Nota: si la línea problemática es de /srv/tramontana/backups, debería llevar nofail y no bloquear el arranque. Si lo bloqueó, añade nofail como parte de la corrección.


CASO 2 — Arranca pero no se puede iniciar sesión

  1. Reinicia. En el menú de GRUB, con la entrada de Ubuntu seleccionada, pulsa e. (Si el menú no aparece: mantén Shift o pulsa Esc repetidamente al encender.)
  2. En la línea que empieza por linux /vmlinuz-, cambia ro por rw y añade al final: init=/bin/bash
  3. Ctrl+X para arrancar.
  4. En el prompt bash-5.2#:
    export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    mount -o remount,rw /
    passwd root                  # o: passwd operador
    
  5. Si la causa fue un cambio en PAM (/etc/pam.d/), restaura la copia: cp /etc/pam.d/common-auth.bak-<fecha> /etc/pam.d/common-auth
  6. Salida limpia — no uses reboot, no hay systemd:
    sync
    exec /sbin/init
    

CASO 3 — Prompt (initramfs)

Suele venir de un cambio en crypttab, LVM o discos sin regenerar el initramfs.

  1. Comprueba si el kernel ve el disco: cat /proc/partitions
    • No aparece el disco → problema de hardware o de driver. Escala; comprueba la configuración de almacenamiento de la VM.
    • Aparece → sigue.
  2. Comprueba si están las herramientas: which cryptsetup lvm
    • Sin salida → falta en el initramfs. Ve al paso 4.
  3. Intenta montar a mano para confirmar que los datos están bien:
    lvm vgchange -ay
    mkdir /raiz && mount -o ro /dev/mapper/<volumen> /raiz && ls /raiz
    
  4. Recuperación rápida: reinicia, y en el menú de GRUB entra en Advanced options for Ubuntu y elige el kernel anterior. Si arranca:
    sudo update-initramfs -u -k all
    sudo lsinitramfs /boot/initrd.img-$(uname -r) | grep -c sbin/cryptsetup   # debe dar 1
    
  5. Si el kernel anterior tampoco arranca: ve al Caso 4 (chroot) y ejecuta ahí los comandos del paso 4.

CASO 4 — No hay GRUB, o nada de lo anterior funciona: chroot de rescate

Procedimiento universal. Requiere el ISO de Ubuntu 24.04 montado en la VM y arrancar en modo Try Ubuntu.

  1. Identifica las particiones: lsblk -f Referencia de srv-tramontana: sda1 = ESP (FAT32), sda2 = /boot, sda3 = raíz.
  2. Monta, en este orden:
    sudo mount /dev/sda3 /mnt
    sudo mount /dev/sda2 /mnt/boot
    sudo mount /dev/sda1 /mnt/boot/efi
    for d in /dev /dev/pts /proc /sys /sys/firmware/efi/efivars /run; do
        sudo mount --bind "$d" "/mnt$d"
    done
    
    ⚠️ efivars no es opcional. Sin él, grub-install falla en UEFI con un error poco claro.
  3. Entra: sudo chroot /mnt /bin/bash
  4. Repara lo que corresponda:
    grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu --recheck
    update-grub
    update-initramfs -u -k all
    efibootmgr -v | grep -i ubuntu      # debe aparecer la entrada
    
  5. Salida limpia, desmontando en orden inverso:
    exit
    for d in /run /sys/firmware/efi/efivars /sys /proc /dev/pts /dev; do
        sudo umount "/mnt$d"
    done
    sudo umount /mnt/boot/efi /mnt/boot /mnt
    sudo reboot
    

CASO 5 — Arranca, pero tarda mucho más de lo normal

No es una emergencia. Referencia normal: ~12 segundos.

  1. systemd-analyze → separa kernel de espacio de usuario.
  2. systemd-analyze critical-chain → esta es la que importa, no blame: una unidad lenta que arranca en paralelo no retrasa el total.
  3. journalctl -b -u <unidad> → la causa concreta.
  4. Corrige con un drop-in en /etc/systemd/system/<unidad>.d/override.conf, nunca editando la unidad original. Si sustituyes un ExecStart, recuerda la línea ExecStart= vacía antes.
  5. Reinicia y vuelve a medir. Anota el nuevo tiempo en la línea base.

REGLAS QUE EVITAN LOS CUATRO PRIMEROS CASOS

Antes de… Haz siempre
Reiniciar tras tocar fstab mount -a y comprobar que no da error
Reiniciar tras tocar crypttab, LVM o discos update-initramfs -u -k all y verificar con lsinitramfs | grep cryptsetup
Tocar PAM o sshd_config Segunda sesión abierta; validar con sshd -t; reload, no restart
Cualquier cambio de configuración Copia .bak-$(date +%F) y diff -u después
Cualquier módulo delicado Snapshot de la VM, numerado

Nunca: GRUB_TIMEOUT=0, GRUB_TIMEOUT_STYLE=hidden, borrar kernels a mano, ni montajes sin nofail salvo la raíz y /boot.

Si nada funciona. No improvises más de 30 minutos. Reconstruye: el RTO acordado es de 8 horas, el runbook de reconstrucción está en este mismo documento, y los datos están en restic con restauración probada. Avisa a Operaciones antes de empezar.

Conclusión

Ya no arrancas un servidor: sabes qué ocurre cuando lo haces. Conoces la cadena completa —firmware UEFI, la ESP y efibootmgr, GRUB con sus fuentes reales de configuración, el initramfs y el círculo vicioso que resuelve, el kernel y su paso de control a PID 1, y systemd activando default.target— y, sobre todo, sabes usar esa cadena como herramienta de diagnóstico: la primera pregunta ante un servidor que no arranca es siempre hasta dónde llegó. Has intervenido en el menú de GRUB, has distinguido rescue de emergency, has arrancado con una shell como PID 1 y has entendido por qué la raíz está en solo lectura. Has reparado un fstab roto —el escenario que 05-04 dejó anunciado—, has recuperado una contraseña de root en dos minutos (y con ello has visto por qué el acceso físico quedaba fuera del modelo de amenazas de 06-06), y has reinstalado GRUB desde un medio de rescate con el chroot completo, incluido el --bind de efivars que hace fracasar la mitad de los intentos. El runbook tiene ahora un árbol de decisión que puede seguir alguien que no seas tú, que es la definición de un procedimiento útil.

Y en el camino has usado chroot para entrar en un sistema de ficheros ajeno y ejecutar programas dentro de él como si fuera la raíz. Recuérdalo: es la primitiva sobre la que se construye todo lo que verás en 07-05, cuando descubras que un contenedor no es una máquina pequeña.

Sabes mirar el arranque, pero todavía no sabes mirar dentro de un proceso en marcha. En el Módulo 5 aprendiste a medir con el método USE: vmstat, iostat, free, sar te dicen que la CPU está al 80 %, que el disco tiene latencia alta o que la memoria se agota. Eso responde a cuánto, pero no a qué. Cuando revision_salud.sh empiece a devolver 1 porque la aplicación tarda 400 ms en responder en lugar de 40, y los contadores digan que la CPU está ociosa, el disco tranquilo y la memoria de sobra, necesitarás otra clase de herramientas. En la lección 07-02: Diagnóstico Avanzado aprenderás a preguntarle al sistema qué está haciendo exactamente un proceso: strace para ver sus llamadas al sistema una por una —cerrando el círculo con las capas del Módulo 1—, perf para perfilar dónde consume ciclos de verdad y leer un gráfico de llama, y eBPF con bpftrace y las herramientas de bpfcc-tools para instrumentar el kernel en producción sin el coste prohibitivo de strace. Y te encontrarás de frente con una consecuencia de tu propio trabajo: el kernel.yama.ptrace_scope = 1 que aplicaste en 06-06 te va a impedir adjuntarte a tus propios procesos, y entender por qué eso está bien es parte de la lección.

Curso de Linux: De Principiante a Administrador de Sistemas

Módulo 1: Introducción a Linux

Módulo 2: Comandos Básicos de Linux

Módulo 3: Habilidades Avanzadas en la Línea de Comandos

Módulo 4: Scripting en Shell

Módulo 5: Administración del Sistema

Módulo 6: Redes y Seguridad

Módulo 7: Temas Avanzados

Módulo 8: Proyectos Prácticos

© Copyright 2026. Todos los derechos reservados