Sinopsis:
El objetivo es arrancar nuestro IoT Gateway con un arranque por red usando iPXE (Preboot Execution Environment) y gracias a los menús de arranque poder hacer una imagen del disco, o restaurarla, usando Clonezilla.
Vídeos
Lista de reproducción con todos los vídeos, aquí.
Tabla de Contenidos:
Esquema del proceso

Image source:
📎 Netboot-Clonezilla.drawio.png 1361.6KB
Descripción del proceso
- Arrancar IoT GW usando el arranque por red.
- El servidor
HTTP serverle servirá un menú de arranque. - El usuario, decide que acción quiere realizar (clonar el disco, o restaurar). Seguidamente se le preguntará por el hostname del ordenador sobre el que quiere actuar.
- Seguidamente el IoT GW le pedirá al servidor HTTP el Kernel (fichero,
vmlinuz), para que arrancar. Además del ficheroinitrd, primer proceso del sistema, y elsquashfsdonde hay la raíz del disco con todos los ficheros de sistema. - Los
startup scripts; son unos simples shell scripts que se descargan delHTTP servery que se ejecutan en cadena. Los archivos se obtienen en formato TAR + GZIP (.tgz) y se descomprimen dentro del directorio/opten el siguiente orden.- Primero se descarga un fichero llamado
boot.tgzy se descomprime en/optEste paquet tiene estos ficheros:boot.config: define variables necesarias para los siguientes scripts mount.sh: mounta del NAS el repositorio donde se localizan las imagenes del disco para ese hostname. backup.sh: lanza el proceso de clonado de clonezilla restore.sh: lanza el proceso de restauración de clonezilla - Después otro fichero llamado
hostname_del_ordenador.tgzy se descomprime en/optSolo hay un fichero en este paquete:hostname_del_ordenador.config: contiene la variable con el nombre de dispositivo (disco) a copiar/clonar o a donde restaurar. - Seguidamente el fichero
/etc/rc.localse encarga de ejecutar la acción seleccionada en el menú de arranque.- Primero, se ejecuta
mount.shpara montar el respositorio de las copias para ese host.En nuestro caso este montaje se hace a través del SSHFS. - Seguidamente en función de la acción escogida en el menú de arranque se lanzará
backup.shorestore.shPara saber cual de los dos scripts hay que lanzar nos fijaremos en el parámetro del kernel llamadoclonezillaEchando un vistazo al fichero/etc/rc.localse puede entender la explicación anterior de una forma más precisa:#!/bin/bash ACTION=$(cat /proc/cmdline | tr ' ' '\n' | grep clonezilla | cut -f 2 -d '=') cd /opt ./mount.sh && ./${ACTION}.sh
- Primero, se ejecuta
- Primero se descarga un fichero llamado
- En este punto ya podemos ejecutar Clonzilla para hacer la copia/clonar el disco, o restuarar una imagen. Recordemos que partimos de un escenario donde hay un Linux corriendo en RAM, en el que en un directorio del sistema de ficheros tenemos montado por SSHFS el repositorio donde colocar la imagen de la copia del disco o desde donde restaurar la imagen.El fichero de copia
backup.sh, tiene esta pinta:#!/bin/bash source /opt/boot.config source /opt/${MAQUINA_ID}.config ocs-sr -senc -noabo -fsck-y -gs -z1p -sc savedisk ${MAQUINA_ID} ${DISK}Detalles del comando de clonezilla y sus parámetros:
ocs-sr: Herramienta de línea de comandos para guardar o restaurar una imagen de disco o partición.senc: Omite la encriptación de la imagen con una frase de paso.noabo: Hace que la imagen de la partición pueda ser accedida por otros usuarios, no solo por el propietario, cambiando los permisos de acceso del archivo de imagen.fsck-y: Ejecuta fsck automáticamente en el sistema de archivos fuente antes de guardarlo. Esta opción intentará corregir automáticamente cualquier corrupción detectada en el sistema de archivos sin pedir confirmación.gs: Genera el checksum SHA1 para la imagen. Esto es útil para verificar la integridad de la imagen al restaurarla, aunque se señala que puede llevar bastante tiempo si el tamaño de la imagen es grande.z1p: Comprime la imagen usando gzip en paralelo (pigz) durante el proceso de guardado. Esta opción es adecuada para aprovechar múltiples núcleos o CPUs, ofreciendo una compresión rápida y eficiente.sc: Omite la verificación de si la imagen puede ser restaurada después de ser creada. Por defecto, Clonezilla verificaría esto, pero con este parámetro, esa verificación se salta.savedisk: Indica que la operación guardará un disco entero en un archivo de imagen.${MAQUINA_ID}: Sería el identificador de la máquina o el nombre de la imagen bajo la cual se guardará el disco. Este parámetro especifica cómo se nombrará la carpeta de la imagen dentro de/home/partimag.${DISK}: El nombre del disco que se va a clonar o guardar. Este puede ser, por ejemplo,sda, y no necesita incluir el prefijo/dev/.
Este comando, en resumen, inicia un proceso para guardar un disco completo (savedisk) en una imagen, omitiendo la encriptación de la imagen, cambiando los permisos para que otros usuarios puedan acceder a la imagen, verificando y corrigiendo automáticamente cualquier error en el sistema de archivos del disco fuente, generando un checksum SHA1 para la imagen, comprimiendo la imagen con gzip en paralelo para una mayor eficiencia, y omitiendo la verificación post-guardado sobre la capacidad de restauración de la imagen.Y el script de restauracionrestore.sh, tiene este contenido:#!/bin/bash source /opt/boot.config source /opt/${MAQUINA_ID}.config ocs-sr -e1 auto -e2 -r -j2 -scr -p reboot restoredisk ${MAQUINA_ID} ${DISK}Detalles del comando y sus parámetros:
ocs-sr: Herramienta de línea de comandos utilizada para guardar o restaurar una imagen de disco o partición.e1 auto: Fuerza el cambio de los valores CHS (cilindros, cabezas, sectores) de la partición de arranque NTFS después de que se restaure la imagen, si "auto" está asignado, Clonezilla detectará automáticamente la partición de arranque NTFS.e2: Fuerza el uso de los valores CHS (cilindros, cabezas, sectores) desde EDD (Enhanced Disk Device) al crear la tabla de particiones con sfdisk.r: Redimensiona la partición cuando finaliza la restauración, ajustando el tamaño del sistema de archivos para que se ajuste al tamaño de la partición. Es útil cuando una imagen de una partición pequeña se restaura en una partición más grande.j2: Utiliza dd para clonar la imagen de los datos entre el MBR (primer sector, es decir, 512 bytes) y la primera partición, lo cual puede ser útil para algunas herramientas de recuperación. Este parámetro solo funciona en el modorestoredisk, no enrestoreparts.scr: Omite la verificación de si la imagen es restaurable antes de restaurarla. Por defecto, Clonezilla realizaría esta verificación.p reboot: Especifica que la máquina se reiniciará automáticamente después de que finalice la restauración de la imagen.restoredisk: Indica que la operación restaurará un disco completo desde un archivo de imagen.${MAQUINA_ID}: Sería el identificador de la máquina o el nombre de la imagen que se va a restaurar. Este parámetro especifica el nombre de la carpeta de la imagen dentro de/home/partimagque se usará para la restauración.${DISK}: El nombre del disco al que se va a restaurar la imagen, por ejemplo,sda. Este puede ser con o sin el prefijo/dev/.
Este comando inicia un proceso para restaurar un disco completo desde una imagen específica, ajustando automáticamente los valores CHS si es necesario, redimensionando la partición para que coincida con el tamaño del sistema de archivos, clonando datos ocultos que podrían ser importantes para algunas herramientas de recuperación, y omitiendo la verificación previa de restauración para agilizar el proceso. Al finalizar, el sistema se reiniciará automáticamente.
Configuración DHCP para arrancar con iPXE
Para que una máquina arranque en red hacen falta diferentes configuraciones.
- La primera depende totalmente de la BIOS del IoT Gateway y en esta no podemos ayudaros mucho, en esencia hay que decirle a la secuencia de arranque que debe empezar buscando un arranque en red.
- Seguidamente hay que tener configurado el servidor DHCP adecuadamente, otro tema que dependerá mucho del servidor DHCP que estemos usando. A cotinuación se describe como se debe configurar
isc-dhcp-serverpara Ubuntu 22.04.Para ser concretos nos interesa configurar la opciónfilename.filename: se puede configurar la ruta del menu de arranque, fichero *.ipxe, con diferentes protocolos. Nosotros hemos usado HTTP para indicar donde se encuentra el servidorHTTP serverdel esquema inicial. La peculiaridad es que esto nos permitiría tener este servidor fuera de la LAN, gracias a que ya tenemos el stack IP configurado.
Ejemplo,subnet 10.147.18.0 netmask 255.255.255.0 { range 10.147.18.25 10.147.18.50; # Change this range as appropriate for your network option subnet-mask 255.255.255.0; option routers 10.147.18.99; # Change this to the address of your router option broadcast-address 10.147.18.255; option domain-name "mynetwork.lan"; # This is optional option domain-name-servers 8.8.8.8; filename "http://example.tld/uri/menu.ipxe"; }
Instalación HTTP server
Se usa docker, más concretamente docker compose para desplegar un simple servidor HTTP (
HTTP server del esquema inicial). Este debe estar accesible por parte de la máquina que debe usar iPXE para arrancar. No hace falta que esten en la misma red; podría estar montado en Internet si hace falta.Este es el fichero
docker-compose.yml, o compose.yml que podéis usar:version: '3.9'
services:
netboot:
image: p3terx/darkhttpd
container_name: netboot
restart: unless-stopped
volumes:
- './assets:/www:ro'
entrypoint: ["/darkhttpd","/www"]
ports:
- 80:80Menús iPXE
Configurar estos menús es un dolor de cabeza. En este caso se ha basado la configuración en los menús de Netboot.XYZ. En case al docker compose se deberá crear un directorio llamado
config dentro del directorio assets. Dentro de este directorio se colocarán los scripts ipxe; los encargados de definir como deben ser los menús que debe mostrar la máquina que arranca por red.Por defecto, netboot.xyz tiene muchos ficheros y opciones para definir un menú lleno de posibilidades, tanto para arrancar distribuciones de Linux live, como para arrancar soluciones de rescate y mucho más.
En este caso se ha reducido el menú a la mínima expresión:

Finalmente en la carpeta config, dejaremos los siguientes ficheros:
menu.ipxe→ definición principal del menúabout.ipxe→ información sobre la versión del menúnetinfo.ipxe→ información de la configuración de red recibida en este puntoversion.ipxe→ información sobre la versión de netboot
Obtención del hostname
Con el fin de facilitar el proceso de copia/clonado y de restauración, se le pregunta al usuario cual es el nombre del
hostname de la máquina sobre la que estamos actuando. Este proceso esta definido dentro de menu.ipxe.Concretamente el código a tener en cuenta es este:
...
echo Please, tell the machine name: (ex. m5)
read maquina_id
...El texto introducido por el usuario quedará registrado en la variable: maquina_id
Esta variable junto con otras se pasarán como parámetros de arranque. En el siguiente apartado se explica como se pasan estos varoles y como se recuperan después.
Recuperación de parámetros de arranque
Cuando se carga el kernel, este va acompañado de una serie de parámetros para indicarle cual debe ser su comportamiento concreto. Por ejemplo, el parámetro quiet sirve para que el kernel arranque en modo silencioso y sin todos esos mensajes detallados al que nos tiene acostumbrado Linux.
Pues bien, todos estos parámetros de arranque los podemos recuperar una vez arrancado el sistema consultando el fichero
/proc/cmdline.En el caso que nos ocupa si miramos concretamente en esta parte del código de menu.ipxe podremos ver todos los parámetros que se pasan al kernel:
...
:clonezilla-boot
imgfree
echo Please, tell the machine name: (ex. m5)
read maquina_id
set ocs_params ocs_live_run="sudo /etc/rc.local"
set extra_params maquina_id=${maquina_id}
set ocs_preload1 ocs_preload1=${live_endpoint}/boot.tgz
set ocs_preload2 ocs_preload2=${live_endpoint}/${maquina_id}.tgz
set path /debian-squash/releases/download/3.1.2-9-80072992/
set url ${live_endpoint}${path}
kernel ${url}vmlinuz boot=live username=user union=overlay config components noswap edd=on nomodeset keyboard-layouts=es locales=en_US.UTF-8 ${ocs_params} ${extra_params} ${ocs_preload1} ${ocs_preload2} ${clonezilla} ocs_live_batch=no ocs_screen_blank="no" net.ifnames=0 nosplash noprompt fetch=${url}filesystem.squashfs initrd=initrd.magic loglevel=3 ${cmdline}
initrd ${url}initrd
boot
...Al prestar atención se ve que hay unos cuantos parámetros que vale la pena comentar; seteo de las variables:
set ocs_params ocs_live_run="sudo /etc/rc.local"- fichero a ejeuctar al arrancarset extra_params maquina_id=${maquina_id}- el nombre de la máquinaset ocs_preload1 ocs_preload1=${live_endpoint}/boot.tgz- scripts de copia y restauración que se descomprimirán en /optset ocs_preload2 ocs_preload2=${live_endpoint}/${maquina_id}.tgz- configuraciones particulares que se descomprimiran en /optset path /debian-squash/releases/download/3.1.2-9-80072992/- ruta donde se encuentran en kernel, initrd y filesystem.squashset url ${live_endpoint}${path}- URL completa desde donde descargar los ficheros
estás variables después se pasan al kernel así:
kernel ${url}vmlinuz boot=live username=user union=overlay config components noswap edd=on nomodeset keyboard-layouts=es locales=en_US.UTF-8 ${ocs_params} ${extra_params} ${ocs_preload1} ${ocs_preload2} ${clonezilla} ocs_live_batch=no ocs_screen_blank="no" net.ifnames=0 nosplash noprompt fetch=${url}filesystem.squashfs initrd=initrd.magic loglevel=3 ${cmdline} Una vez ha iniciado el sistema como en
/proc/cmdline hay todos los parámetros del kernel.De forma que con simples scripts de shell se puede extraer sus valores, por ejemplo el hostname:
cat /proc/cmdline | tr ' ' '\n' | grep maquina_id= | cut -f 2 -d '='Cambios en el squashfs original
Netboot.xyz ofrece varias imagenes de Clonezilla, para ser más exactos 4; un par para Debian y otras dos para Ubuntu. En sus versiones estables y de desarrollo.
A pesar de que las imágenes son muy parametrizables a través de los parámetros del kernel, hay algunas funciones que se echaban de menos.
Basándonos en la imagen Debian estable, se ha modificado la imagen original; con los siguientes cambios:
Paquetes añadidos: btop y byobu
- btop - ideal para observar el rendimiento de la máquina
- byobu - muy cómodo para dejar procesos corriendo sin que se interrumpan al perder la conexión, además de poder compartir consola. Muy útil para soporte remoto.
Cambios relativos al SSH
- Añadido el servicio de sistema para que este siempre corriendo.
- Se permite acceso a root remotamente.
- Se asigna contraseña de root que por defecto no había.
- Se añaden claves públicas de los administradores en
~/.ssh/authorized_keys.
Servicio rc.local
- Añadido nuevo servicio de sistema para ejecutar comandos a medida al arrancar.
Modificaciones en /etc/profile
- Definida variable de entorno MAQUINA_ID con el hostname de la máquina
- Se usa esta variable para cambiar el nombre de la máquina live, así se hace más cómodo saber con que máquina se esta interactuando.
Como se introducen cambios en un sistema de ficheros squash
A partir de la web de Netboot.XYZ se puede descargar la imagen que interese. En este caso se descarga la versión de Clonezilla estable basada en Debian.
Se asume que se ha copiado y dejado en el directorio el fichero squashfs de clonezilla:
apt install -y squashfs-tools
cd clonezilla
sudo unsquashfs filesystem.squashfsdentro del directorio:
squashfs-root se pueden hacer los cambios que se necesiten squash.filesystem; una buena recomendación es montarlo en chroot para poder usar cosas como el sistema de paquetes y otros similares.Para trabajar en chroot, una buena idea es usar esta secuencia de comandos:
sudo mount --bind /dev squashfs-root/dev
sudo mount --bind /proc squashfs-root/proc
sudo mount --bind /sys squashfs-root/sys
sudo chroot squashfs-rootLlegados a este punto se tiene acceso a una shell donde podemos hacer los cambios que queramos en la imagen.
Una vez listos los cambios para salir del entorno chrooted:
# inside chroot, run:
exit
# when chroot exits, run:
sudo umount -l squashfs-root/dev
sudo umount -l squashfs-root/proc
sudo umount -l squashfs-root/sysFinalmente, para crear la nueva imagen del squashfs se puede ejecutar:
sudo mksquashfs squashfs-root filesystem.squashfs -b 1024k -comp xz -Xbcj x86 -e boot
Ahora solo falta mover el fichero
filesystem.squashfs y copiarlo para que sea accesible des el servidor HTTP (HTTP server del esquema).Script que se ejecuta post-booting rc.local
Este script es parte del
squash.filesystem; por lo tanto no es buena idea ir modicándolo ya que después se deberá volver a crear el fichero squash y distribuirlo al servidor.Por lo tanto interesa que el contenido de este script sea muy sencillo y flexible a la vez, así es como se ha diseñado:
#!/bin/bash
ACTION=$(cat /proc/cmdline | tr ' ' '\n' | grep clonezilla= | cut -f 2 -d '=')
cd /opt
./mount.sh && ./${ACTION}.shSe puede observar que lo primero es descubrir si queremos hacer un backup, o restaurar. Información almacenada en el parámetro del kernel clonezilla y guardamos este valor (backup|restore) en la variable ACTION.
A continuación ejecutamos el script
mount.sh y si todo va bien, el script que tiene el nombre de la acción recuperada: backup o restore.Montaje del repositorio mount.sh
Tal y como indica su nombre el objetivo del script es montar la unidad de red donde hay las copias de seguridad de la máquina.
Este script se encuentra dentro de
boot.tgz; al arrancar la distro live se descomprime este paquete en /opt. Allí es donde se encuentra el script mount.sh. El encargado de ejecutar el script es /etc/rc.local. Un ejemplo del contenido del script mount.sh:
#!/bin/bash
source /opt/boot.config
source /opt/${MAQUINA_ID}.config
mkdir -p /home/partimag/${MAQUINA_ID}
sshfs ${SSHFS} ${DESTPATH} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o Compression=no
if [ $? -ne 0 ];
then
echo "Error mounting backup"
exit 1;
fi
echo "Backup mount point: ${DESTPATH}"
exit 0Podemos obsevar que el montaje se hace con SSHFS, esto implica que previamente ya se ha instalado la clave pública de SSH que hay en la live que estamos ejecutando al servidor NAS que nos esta ofreciendo el acceso por SSH, concretamente la clave púlica la hemos puesto en el fichero
~/.ssh/authorized_keys.Copia y restauración del disco, scripts: backup.sh y restore.sh
Tal y como hemos visto en el punto anterior,
backup.sh y restore.sh se distribuyen empaquetados en boot.tgz y este fichero se recoge del servidor local de Netboot.XYZ. Su nombre describe claramente su cometido y el contenido del script es realmetne senzillo:backup.sh
#!/bin/bash
source /opt/boot.config
source /opt/${MAQUINA_ID}.config
ocs-sr -senc -noabo -fsck-y -gs -z1p -sc savedisk ${MAQUINA_ID} ${DISK}restore.sh
#!/bin/bash
source /opt/boot.config
source /opt/${MAQUINA_ID}.config
ocs-sr -e1 auto -e2 -r -j2 -scr -p reboot restoredisk ${MAQUINA_ID} ${DISK}
Como se puede ver, simplemente se cargan las variables genéricas
boot.config y las específicas de la máquina a restaurar ${MAQUINA_ID}.config y se ejecuta el comando de Clonezilla que se ha descrito al inicio de este documento.Ficheros de configuración para boot.tgz y <hostname>.tgz
En la carpeta
assets se esperan los ficheros boot.tgz y almenos un <hostname>.tgz; evidentemente puede haber tantos ficheros de host como equipos se quieran manejar.Para ser más concretos la operativa recomendada, para crear
boot.tgz podría ser:Una vez creados los ficheros, desde dentro del directorio boot, se puede ejecutar el siguiente comando:
cd boot
rm ../boot.tgz || tar cvfz ../boot.tgz .Aquí hay un ejemplo de como debería quedar el paquete.
📎 boot.tgz 0.6KB
Para crear un fichero
<hostname>.tgz; asumiremos que hostname=m5, por lo tanto el fichero será: m5.tgz. El procedimiento es análogo aunque no hace falta tantos ficheros.Una vez creados los ficheros, desde dentro del directorio boot, se puede ejecutar el siguiente comando:
cd m5
rm ../m5.tgz || tar cvfz ../m5.tgz .Aquí hay un ejemplo de como debería quedar el paquete.
📎 m5.tgz 0.2KB
Conclusión
Los procedimientos descritos distan de ser simples y fáciles de entender. Pero el valor que añaden en pro de la automatización y la rápida recuperación en caso de desastre son realmente remarcables. Por lo tanto, a día de hoy es la mejor solución que hemos sabido encontrar para llevar a cabo este servicio.
Recursos
- netboot.xyz
- linuxserver.io - netboot.xyz
- Referencia de comandos para menú iPXE
- Clonezilla booting parameters


