Ir al contenido

Blog ·

De una respuesta DHCP a una instalación acabada

Netboot, segunda parte. Qué pasa tras la oferta: el script de arranque, el fichero de respuestas, el aviso que nadie escribe y quién publica sumas.

Por Provibr

Conseguir que una máquina acepte una oferta de netboot es la parte sobre la que escribe todo el mundo. Nosotros también escribimos sobre ella, después de perder una semana con la dirección de destino de una respuesta de proxy DHCP.

La parte siguiente casi no se cubre, y es donde viven los fallos de verdad. Una máquina que arranca y luego se queda para siempre esperando en una pregunta es peor que una que no arrancó nunca, porque parece progreso. Esta es la segunda mitad: qué tiene que ser cierto entre la llegada de la oferta y la aparición de un indicador de inicio de sesión, y cuáles de esas cosas fallan en silencio.

Las cinco cosas que se sirven

Una vez que el cliente tiene una oferta y un fichero de arranque, una instalación desatendida son cinco artefactos. Ninguno de ellos es opcional, y el último es el que la gente se deja fuera.

#QuéLo sirveCómo falla
1Script de arranqueHTTPLa máquina cae a un intérprete de órdenes
2KernelHTTPEl arranque se aborta
3InitrdHTTPEl arranque se aborta
4Fichero de respuestasHTTPEl instalador hace una pregunta y espera
5Aviso de finalizaciónEl sistema instaladoTodo se queda colgado hasta un plazo límite

La columna interesante es la última. Los puntos 1 a 3 fallan a gritos, en pantalla, de una forma que alguien nota. Los puntos 4 y 5 fallan como una instalación que parece estar en marcha y no termina nunca.

Los scripts de arranque y el problema del marcador

El script de arranque tiene que nombrar URL absolutas, y no puede conocerlas cuando se escribe el perfil: la dirección de lo que sirva los ficheros depende del segmento en el que arrancó la máquina.

Por eso el perfil contiene un marcador que se sustituye en el momento de servir. El nuestro es @@PROVIBR_BASE@@, y su forma es una elección deliberada y no una preferencia de estilo.

La forma obvia sería ${BASE}. Y es justo la equivocada, porque iPXE expande ${...} por su cuenta. Una sustitución que no llega a ocurrir se convierte en una cadena vacía en lugar de en un error, y uno acaba mirando fijamente

text
chain http:///vmlinuz

y preguntándose qué le pasa al servidor web. Un delimitador que el cargador de arranque no reconoce convierte un fallo de sustitución silencioso en uno visible.

Las tres líneas de comandos de kernel que importan, una vez retirada la marca:

text
# Ubuntu (subiquity)
kernel <kernel> initrd=<initrd> ip=dhcp autoinstall ds=nocloud;s=<dir>/ --- || goto failed

# Debian (preseed)
kernel <kernel> initrd=<initrd> auto=true priority=critical ip=dhcp url=<file> DEBIAN_FRONTEND=text --- quiet || goto failed

# RHEL family (Anaconda)
kernel <kernel> initrd=<initrd> ip=dhcp inst.repo=<tree> inst.ks=<file> inst.text || goto failed

Tres instaladores, tres vocabularios completamente distintos para la misma idea, y el argumento que lleva el fichero de respuestas se escribe de forma diferente en cada uno. ds= toma un directorio; url= e inst.ks= toman un fichero. Confundirlo da un instalador que arranca y a continuación hace la primera pregunta.

Las cuatro claves de autoinstall que deciden si termina

El autoinstall de Ubuntu merece su propio párrafo, porque en un segmento aislado cuatro claves separan una instalación que termina de una que no, y ninguna de ellas trata de discos ni de usuarios:

  • interactive-sections: []: sin esto, subiquity sigue parándose a preguntar algo.
  • refresh-installer.update: false: sin esto, primero se pone a buscar un instalador más nuevo.
  • apt.fallback: offline-install: sin esto, espera al archivo de paquetes antes de rendirse.
  • drivers.install: false: la misma clase de problema, el mismo resultado.

El fallo es el mismo en todos los casos: una pantalla que parece ocupada. No hay error, porque desde el punto de vista del instalador no ha ido nada mal.

Hay una opción equivalente para el medio. El initrd de netboot de Ubuntu descomprime un medio de instalación en un tmpfs e instala desde ahí; si no se le dice dónde está ese medio, se va a internet a buscar uno. En un segmento sin enlace de subida, esa es la diferencia entre funcionar y cuatro minutos de nada seguidos de un indicador de busybox.

El aviso que nadie escribe

El punto 5 de la lista es una sola línea en un script posterior a la instalación que descarga una URL, y es la pieza que más a menudo falta en un montaje casero.

Sin él no hay ningún evento que signifique terminado. El instalador reinicia, la máquina arranca, y el sistema que lanzó la instalación no se entera de nada, así que espera al plazo que tenga y luego informa de un tiempo agotado en una máquina que se instaló perfectamente.

Dos detalles hacen esto menos molesto de lo que suena. Primero, incluir el gancho en la plantilla en lugar de documentarlo, para que quien escriba su propio script posterior a la instalación no tenga que saber que existe. Segundo, tener un gancho de fallo además de uno de éxito: una instalación que falla a las 04:00 y lo dice es una experiencia de soporte distinta de una que se queda callada.

Y llevar dos relojes, no uno. El comando que lanza una instalación debería completarse en cuanto los servicios de escucha están arriba y la sesión está aceptada, no cuando termina la instalación; el nuestro tiene un plazo de 90 segundos para eso, frente a un presupuesto de instalación de una hora que se aplica por los dos lados. Un solo plazo para las dos cosas significa o bien un trabajo que se queda una hora en la interfaz sin hacer nada, o bien una instalación abortada por tardar lo que tardan las instalaciones.

Qué fabricantes publican una suma de comprobación, medido

Si la máquina descarga un kernel y un initrd por HTTP desde una réplica, algo debería verificar lo que llegó. La manera de hacerlo es fijar un sha256 en el perfil y comprobarlo después de la descarga, en el sitio que hace la descarga.

Eso solo funciona si el fabricante publica una. Supusimos que la respuesta era «en su mayoría no», lo dejamos escrito, y resultó estar equivocado en tres de cada cuatro casos. Lo que se publica realmente, medido el 2026-09-02:

FabricanteKernel + initrd de netbootDónde
DebianSíSHA256SUMS junto a installer-amd64/current/images/
Familia RHELSí[checksums] en el .treeinfo junto al árbol
Ubuntu (ISO live server)SíSHA256SUMS junto a la publicación
Ubuntu (kernel + initrd de netboot)NoNo hay fichero de sumas en el directorio de netboot, y el tarball tampoco aparece en las sumas de la publicación

El coste de esa suposición equivocada no fue una caída; fue peor de una manera silenciosa. Recursos que se podrían haber fijado quedaron marcados como no verificables, y algunos perfiles se declaraban no instalables mientras el fabricante publicaba la respuesta a la vista de todos. Cuatro de cinco artefactos en los dos primeros perfiles.

El comportamiento para cuando de verdad no existe una suma merece diseñarse a propósito. El nuestro deja la fijación vacía, marca el recurso como pendiente, y el perfil se declara no instalable hasta que un administrador pega un hash. Eso es deliberadamente más ruidoso que descargarlo de todas formas. Un kernel sin verificar descargado por HTTP desde una réplica es el punto más valioso para atacar un sistema de aprovisionamiento, y «no pudimos verificarlo así que lo hicimos igualmente» no es una política.

Qué se le permite significar a «mantenido»

Enviamos diez perfiles base: Ubuntu Server 24.04 y 26.04, Debian 12 y 13, Rocky Linux 9 y 10, AlmaLinux 9 y 10, CentOS Stream 10 y Fedora Server 44.

El estado de soporte que lleva cada uno es calculado, no escrito a mano. Un perfil solo puede llamarse mantenido cuando tiene una ejecución verificada en los dos caminos de firmware, BIOS y UEFI. Uno de los dos da «vista previa». Ninguno de los dos da «sin mantenimiento».

Convertir eso en una regla en lugar de en un campo compensa la pequeña cantidad de código. Una etiqueta escrita a mano vale exactamente lo que valga el cuidado de quien la escribió, y esta es una etiqueta de la que un cliente se fía para poner una máquina encima.

Lo cual obliga a ser claro sobre dónde deja eso las cosas hoy. Ubuntu Server 26.04 y Debian 13 se han instalado solos, de forma totalmente desatendida, en un segmento aislado y en una máquina BIOS. El camino de UEFI se reparó en la misma ronda, y repararlo no es lo mismo que ejecutarlo. Por tanto, en el momento de escribir esto ningún perfil de serie está maintained, y los perfiles de la familia RHEL no se han ejecutado en una máquina real en absoluto: se escribieron a partir de la documentación del fabricante y se contrastaron con ficheros de origen reales, que es una afirmación más débil de lo que parece desde fuera.

Aparte de eso, ofrecer netboot como forma de crear una máquina nueva está desactivado por defecto en nuestra plataforma, a la espera de exactamente una cosa: una máquina real instalándose así, sobre firmware real. El camino que sí existe y se usa es la reinstalación sobre una máquina existente. Un interruptor de función encendido porque el código está escrito, y no porque se haya observado que la cosa funciona, produce un botón de pedido que se queda a medias con el primer cliente real.

Cosas pequeñas que cuestan una tarde cada una

  • Validar las rutas de los ficheros servidos. Sin barra inicial, sin .., sin barras invertidas, una sola clase de caracteres. Lo que sirve los ficheros está dentro de la red de alguien, con un sistema de ficheros detrás.
  • Censurar la fila de auditoría. Registrar qué fichero se sirvió y si llevaba un secreto, nunca el contenido. Quien necesite el contenido puede volver a generar el perfil.
  • No dejar que el fichero de respuestas sea una segunda fuente de verdad sobre el medio. El argumento del kernel y el fichero de respuestas nombran los dos de dónde vienen los paquetes; derivar ambos de un solo ajuste es la única manera de que sigan siendo iguales.
  • Suponer que nadie está mirando la consola. Cada elección anterior es una elección sobre lo que ocurre cuando la instalación va por el minuto seis de ocho y no hay ningún humano en la sala.

Esta es la segunda parte del artículo sobre por qué el netboot con UEFI falla donde el BIOS funciona, y salió de construir la instalación por red en Provibr. Los detalles están en la documentación de netboot.

Empiece con un host y un agente

Cree una cuenta, instale el agente con un solo comando y conecte su primer host de Proxmox. El periodo de prueba dura 14 días y no pide ningún dato de pago.