En corto
| |
Y netconsole hacia otra máquina para saber por qué se cayó (abajo).
El problema
Un host con el root cifrado con LUKS (solo passphrase, sin TPM) se congela a media mañana. No hay corte de luz, el journal se corta a mitad de una línea, sin errores. Nadie se entera hasta que alguien llega y lo prende a mano: seis horas abajo.
Tres cosas alargan la caída y borran la evidencia:
| Problema | Consecuencia | Arreglo |
|---|---|---|
| Sin watchdog | Un kernel congelado espera a un humano | Watchdog de hardware alimentado por systemd |
kdump activo (default de Ubuntu) con kernel.panic=0 | El kernel de captura necesita la passphrase para escribir en /var/crash, arranca sin USB ni red y espera para siempre | Apagar kdump, kernel.panic=10 |
| Root con LUKS solo con passphrase | Cualquier reinicio sin nadie enfrente se queda en el prompt | dropbear en el initramfs |
| Un congelamiento duro no deja nada en el journal local | No hay forma de saber la causa | netconsole a otra máquina |
1. Watchdog de hardware y reinicio en panic
En equipos Intel el watchdog del chipset es iTCO_wdt. Ubuntu pone en lista negra todos los drivers de watchdog, pero eso solo evita la carga automática; cargarlo por nombre funciona:
| |
systemd lo alimenta. Si PID 1 deja de hacerlo durante 60 s (kernel congelado), el chipset reinicia la máquina. RebootWatchdogSec acota además los apagados que se quedan colgados:
| |
| |
Para que los panics y lockups reinicien en vez de quedarse colgados:
| |
kernel.printk = 5 … sube el nivel de consola para que los warnings también salgan por netconsole (paso 3). hardlockup_panic necesita el NMI watchdog, que viene encendido por defecto.
kdump: con el root cifrado y sin desbloqueo automático, su kernel de captura no puede escribir el dump y se queda en el prompt de la passphrase. Apágalo:
| |
Y recupera la memoria que reserva. kdump-tools.cfg agrega crashkernel= desde /etc/default/grub.d/, y esos archivos se leen en orden alfabético: un archivo que lo quite tiene que ordenarse después de él (zz-, no 99-):
| |
Así una actualización del paquete no lo regresa.
2. Desbloquear LUKS por SSH con dropbear
dropbear-initramfs mete un servidor SSH mínimo en el initramfs, que arranca antes de abrir el disco:
| |
Opciones en /etc/dropbear/initramfs/dropbear.conf (en versiones viejas de Debian/Ubuntu el archivo es /etc/dropbear-initramfs/config):
| |
| Opción | Para qué |
|---|---|
-p 2222 | Otro puerto que el sshd real: el host key es distinto y así known_hosts no choca |
-s | Sin passwords, solo llaves |
-j -k | Sin port forwarding |
-I 300 | Corta sesiones inactivas a los 5 min |
-c cryptroot-unlock | Cualquier login corre cryptroot-unlock y nada más |
IFDOWN="*" | Al terminar, baja y limpia la NIC para que el sistema real la configure desde cero (importante si encima va un bridge) |
Llaves públicas con restricciones, una por línea:
| |
Red del initramfs con IP fija, sin tocar GRUB (sintaxis de ip= del kernel: cliente::gateway:máscara:hostname:interfaz:autoconf):
| |
Usa la NIC física. Si el sistema tiene un bridge (br0), en el initramfs todavía no existe: pon la interfaz que es su uplink.
Reconstruye y comprueba que todo quedó adentro:
| |
Desbloquear
| |
Escribes la passphrase, la sesión se cierra sola y el arranque sigue. El teclado local sigue funcionando en paralelo: gana el primero que conteste. La primera vez compara el host key con los de /etc/dropbear/initramfs/dropbear_*_host_key:
| |
3. netconsole: que el log del cuelgue sobreviva
Un congelamiento duro no alcanza a escribir nada en disco. netconsole manda los mensajes del kernel por UDP a otra máquina, desde el propio kernel (netpoll), así que llegan aunque el userspace ya esté muerto.
En el host, por configfs y después de que exista la interfaz. La opción del módulo (netconsole=… en la línea de comandos) corre antes de que NetworkManager arme un bridge y no sirve:
| |
Mételo en un servicio oneshot con After= y BindsTo= sobre sys-subsystem-net-devices-br0.device, para que se arme en cada arranque. Si el bridge se recrea con el sistema arriba, el target no se rearma solo: reinicia el servicio.
En la otra máquina (física, en el mismo segmento: una VM sobre el mismo host se cae con él), un receptor con socat que solo acepta a ese host y escribe al journal:
| |
| |
La línea netconsole: … streaming marca cada arranque; lo que está antes de la última marca es el final del arranque anterior. Busca Kernel panic, soft lockup, hard LOCKUP, NVRM: Xid o errores AER de PCIe/Thunderbolt.
Probarlo
| |
La prueba completa, solo con alguien listo para desbloquear: echo c > /proc/sysrq-trigger provoca un panic. El texto debe llegar al receptor, el host reinicia a los 10 s y espera en el prompt de LUKS.
Trampas
- El kernel anterior no trae dropbear.
update-initramfs -usolo reconstruye el initramfs del kernel en uso. Si arrancas el kernel anterior desde GRUB (la salida normal cuando uno nuevo falla), su initramfs puede ser de antes de instalar dropbear: ahí solo sirve el teclado. Revisa conlsinitramfso reconstrúyelo conupdate-initramfs -u -k <versión>. - Solo desde la LAN. En el initramfs no hay VPN ni Tailscale. Para desbloquear desde fuera, anuncia la IP del host (
/32) desde un subnet router que viva en otra máquina de la LAN. - “Host key changed”. El puerto 2222 tiene llaves distintas del sshd normal; la entrada de
known_hostses[192.168.1.20]:2222. - La NIC equivocada. Si el cable está en un adaptador USB o en un dock y la IP está en la integrada, el initramfs no tiene red. En la consola local busca
IP-Config: eno1 …. - netconsole no aparece en
tcpdumpdel propio host: netpoll se salta los puntos de captura. Mira en el receptor. - Solo salen los mensajes con nivel menor a
console_loglevel: con5salen warnings y peores, nuncainfonidebug. - Falsos positivos del watchdog: si systemd se queda 60 s sin alimentarlo, reinicia y vuelves a escribir la passphrase. Para depurar el kernel, quita el
.confysystemctl daemon-reexec. - TPM2/clevis desbloquearía solo, pero también para cualquiera que se lleve el equipo y lo prenda. Aquí se prefirió la passphrase por SSH.