Imagen del Post

Objetivo:

En este artículo la finalidad es crear una forma de instalar automáticamente un sistema Debian 12 (en este caso), de manera que la instalación no sea interactiva, es decir, que el usuario final no tenga que hacer nada ni tener conocimientos previos avanzados para poder tener el sistema operativo preparado para usar. Esto es útil para la creación de máquinas nuevas automáticamente.

Pasos Previos:

  • Para comenzar, parto de una máquina cualquiera en local que hará de servidor (por ejemplo usando Virt Manager).

  • Obtener mediante la página oficial de Debian, o por internet el archivo preseed.cfg que es el encargado de indicarle al sistema en el momento que se esta instalando, las configuraciones necesarias. En este caso, he dejado el que he usado ya configurado, al final del artículo (Ve abajo del todo.)

  • El siguiente paso que he hecho ha sido crear una red llamada "px2" y le he añadido una interfaz al servidor que conecta con esta red (desde ajustes de Virt manager de la propia máquina).

  • Las direcciones ips de mi máquina que hace de servidor son:

La que sale a internet: enp1s0: 192.168.122.22/24

La que conecta con la red px2: enp7s0: 10.0.0.30/24

Imagen del Post

Empezamos!

Bien, con la red configurada el primer paso es instalar el paquete dnsmasq que incluye el paquete dhcp necesario para que las máquinas clientes puedan obtener una configuración de red. Para instalarlo y ver el estado es con:

sudo apt install dnsmasq
sudo systemctl status dnsmasq

Imagen del Post

El siguiente paso es configurar dnsmasq pero antes, hay que crear el directorio que se va a usar (o dará error) que en este caso es /srv/tftp.

Hecho esto ahora hay que ir al archivo /etc/dnsmasq.conf añadiendo al final esta configuración:

#Servidor DHCP
dhcp-range=10.0.0.10,10.0.0.100,255.255.255.0,12h

#Preseed
dhcp-boot=pxelinux.0
#Servidor TFTP
enable-tftp
#directorio archivos
tftp-root=/srv/tftp
Donde indico el `rango de red para dhcp` acorde a mi red px2 que use las direcciones de la `10.0.0.10 a la 10.0.0.100` (esto es completamente configurable, si hubiese más equipos, se amplia el rango, es decir, en vez de poner 100 puedo poner por ejemplo 200). También como dije antes, hay que indicar el directorio de trabajo, donde después habrá que introducir unos archivos que ahora veremos.

Y reinicio el servicio para que cargue la nueva configuración con:

sudo systemctl restart dnsmasq

Ahora entro a mi directorio /srv/tftp y descargo netboot, para ello uso la herramienta wget para obtener el archivo (la url puede variar con el paso del tiempo):

sudo wget http://ftp.debian.org/debian/dists/bookworm/main/installer-amd64/current/images/aso/netboot/netboot.tar.gz

En la imagen de abajo muestro los pasos anteriores. Si falla, recordad usar sudo (pero con cuidado!, sólo si es necesario). La orden mkdir -p crea el directorio junto con los subdirectorios que le indico, para que sea más rápido que hacer varias veces mkdir, cd, etc. Cuando termina de descargar, obtenemos un archivo llamado netboot.tar.gz.

Imagen del Post

Y descomprimo los archivos con:

sudo tar -xvf netboot.tar.gz

Imagen del Post

El siguiente paso es instalar apache2 para poder brindar a cualquier equipo cliente que necesite mi preseed para poder hacer la instalación automatizada. El archivo preseed.cfg hay que copiarlo al directorio /var/www/html de la máquina servidor, es decir, con la que estamos trabajando todo el tiempo (lo especifico para que no haya dudas si es cliente o servidor, etc), para que pueda brindarlo por red usando apache.

sudo apt install apache2

Copio mi archivo preseed.cfg que lo tengo en /home/debian/ a /var/www/html/:

sudo cp /home/debian/preseed.cfg /var/www/html/

Imagen del Post

Ahora toca modificar el archivo /srv/tftp/debian-installer/amd64/boot-screens/txt.cfg (/srv/tftp es mi directorio que he elegido) que por si acaso, hice una copia de seguridad del archivo, el archivo txt.cfg le he especificado una entrada llamada Desatendida 2 andres (a modo de ejemplo) que luego aparecerá en el grub de arranque.

Se puede configurar para que arranque directamente, pero he preferido hacerlo de esta manera para que realmente se aplique la entrada que he creado. Mi configuración es la siguiente:

default install

label install
    menu label ^Install
    kernel debian-installer/amd64/linux
    append vga=788 initrd=debian-installer/amd64/initrd.gz --- quiet

label unattended-gnome
    menu label ^Desatendida 2 andres
    kernel debian-installer/amd64/linux
    append vga=788 hostname=debian domain='' initrd=debian-installer/amd64/initrd.gz url=http://192.168.122.22/preseed.cfg locale=es_ES console-setup/ask_detect=false keyboard-configuration/xkb-keymap=es ---

Donde especifico la ip de mi servidor donde esta el preseed, y un par de parámetros extra de entrada, para evitar errores ocasionales (hice una copia del archivo como se ve también en la imagen de más abajo).

Una vez modificado el archivo txt.cfg reinicio dnsmasq para que se apliquen los cambios reiniciando el servicio:

sudo systemctl restart dnsmasq

Y compruebo que no haya errores en la configuración con:

sudo systemctl status dnsmasq

Imagen del Post

Antes de terminar con el servidor hay que activar el bitforwarding para el reenvio de paquetes, modificando el archivo /etc/sysctl.conf y descomentando la linea (así quedará permanente):

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

Y para que se aplique:

sudo sysctl -p

Imagen del Post

En el siguiente paso (ya quedan pocos!) hay que añadir una regla con iptables al servidor para permitir que los clientes tenga internet y pueda descargar paqueteria y para ello hay que instalar iptables (si no se tuviese ya):

sudo apt install iptables

Una vez instalado, como superusuario le especifico la regla para los equipos en mi red, que como recordatorio es la 10.0.0.0/24 y mi interfaz es enp1s0. Esto permitirá a los clientes que se conecten y obtengan ip del rango que especifiqué antes, tengan salida a internet.

iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o enp1s0 -j MASQUERADE

Imagen del Post

En el cliente:

Para crear un cliente usando virtmanager, hay que ir a nueva y a manual:

Imagen del Post

Luego como es Debian, elijo Debian 11 (porque en mi versión de virtmanager es la mas reciente, pero funciona igualmente en Debian 12), luego le asigno un disco, ram, etc y cuando me pregunte el nombre para terminar, hay que darle a personalizar antes de instalar.

Imagen del Post

En opciones de arranque hay que indicarle que primero compruebe por red (poniendo la opción NIC como la primera):

Imagen del Post

Luego al iniciar la máquina aparece información varia de lo que esta ocurriendo:

Imagen del Post

Cuando termina y aparece el grub de Debian 12, aparece Desatendida 2 andres que es la entrada que puse en el archivo de configuración del txt.cfg de antes.

Imagen del Post

Y cuando termina la instalación, hay que parar la máquina e indicarle que arranque desde el disco duro volviendo a poner en primer lugar la opción Virt para poder cargar el sistema:

Imagen del Post

Hecho esto ya hemos terminado!, como se ve en la máquina cliente tiene salida a internet y tambien se resuelven los nombres de dominio (resolución DNS):

Imagen del Post

Solución de Posibles Errores:

Al reiniciar el servidor, hay que asegurarse que el bitforwarding sigue activado (aunque esta puesto como permanente) y volver a introducir la regla de iptables (ya que no esta permanente, buscad información si interesa para hacerlo permanente a reinicios) y comprobar si dnsmasq esta activo.

Si al probar dias despues, pasara algo extraño, como que se empiezan a descargar los paquetes, pero para algunos salta un error de réplica, lo tengo puesto en el presed a deb.debian.org y lo he modificadlo a ftp.debian.org. Es un error extraño porque haciendo alt+f2 y entrar en el modo consola, la máquina hace ping tanto a los dns de google 8.8.8.8, a google.com y a debian. Lo curioso es que al darle a reintentar, la instalación continua y acaba bien. Es muy extraño, buscando informacion en internet puede ser una caida puntual de internet. Dejo una captura del mensaje:

Imagen del Post

Justo despues funciona bien y se sigue instalando.

Imagen del Post

Si os pasa, ocurre cuando descarga el paquete liblzo2-2udeb que sirve para el instalador de debian con el algoritmo LZ0, aunque no deberia de ocurrir.

Nota Importante:

Mi preseed.cfg contiene un usuario llamado andres y una clave cifrada, para poder adaptar esto a otros usuarios, hay que modificar el nombre (obvio) y el campo de password por una contraseña cifrada que TÚ elijas. Si usas mi preesed directamente sin modificarlo, cuando termines no podrás iniciar sesión ya que estará el usuario andres y mi contraseña. Lo mismo aplica para root.

Para introducir otra contraseña, puede ser en texto claro o cifrada como yo hice. Usé el algoritmo SHA-512, por eso empieza por $6$.

Con el paquete whois se puede generar otra password así:

mkpasswd -m sha-512

Esto pedirá que se introduzca una contraseña y la devolverá ya cifrada. Eso es lo que hay que poner en el preseed en vez de la mia que empieza por $6$ en la parte de Accounts

Preseed.cfg

# Local
d-i debian-installer/language string en_GB:en
d-i debian-installer/country string ES
d-i debian-installer/locale string en_GB.UTF-8


# Keyboard
d-i keyboard-configuration/xkb-keymap select es


# Network
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string andres
d-i netcfg/get_domain string unassigned-domain
d-i netcfg/wireless_wep string


# Mirror
d-i mirror/country string manual
d-i mirror/http/hostname string ftp.es.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string
d-i mirror/suite string stable


# Accounts
d-i passwd/root-password-crypted password  $6$bfZ4HnT1IB3XFz3s$w20.nob/mS71wYqyVFen3V4H6VY8no7j30roJYQ3s0OLHBNDhfPqrMRYDpeRga9/sclRvLNh5eC4rwiXZsAwA0
d-i passwd/user-fullname string andres
d-i passwd/username string andres
d-i passwd/user-password-crypted password  $6$bfZ4HnT1IB3XFz3s$w20.nob/mS71wYqyVFen3V4H6VY8no7j30roJYQ3s0OLHBNDhfPqrMRYDpeRga9/sclRvLNh5eC4rwiXZsAwA0

# Clock and time zone
d-i clock-setup/utc boolean true
d-i time/zone string Europe/Madrid
d-i clock-setup/ntp boolean true


# Partitioning
d-i partman-auto/disk string /dev/vda
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-auto/method string lvm
d-i partman-lvm/confirm boolean true
d-i partman-auto/choose_recipe select mypartitioning
d-i partman-auto-lvm/new_vg_name string vg00
d-i partman-auto-lvm/guided_size string max
d-i partman-lvm/confirm_nooverwrite boolean true

d-i partman-auto/expert_recipe string                         \
      mypartitioning ::                                       \
              512 1 512 xfs                                   \
                      $primary{ } $bootable{ }                \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ xfs }     \
                      mountpoint{ /boot }                     \
              .                                               \
              1024 1 1024 linux-swap                          \
                      $defaultignore{ }                       \
                      $lvmok{ }                               \
                      lv_name{ swap }                         \
                      in_vg { vg00 }                          \
                      method{ swap } format{ }                \
              .                                               \
              3072 1 3072 xfs                                 \
                      $defaultignore{ }                       \
                      $lvmok{ }                               \
                      lv_name{ root }                         \
                      in_vg { vg00 }                          \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ xfs }     \
                      mountpoint{ / }                         \
              .                                               \
              6144 1 6144 xfs                                 \
                      $defaultignore{ }                       \
                      $lvmok{ }                               \
                      lv_name{ var }                          \
                      in_vg { vg00 }                          \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ xfs }     \
                      mountpoint{ /var }                      \
              .                                               \
              8192 1 1000000000 xfs                           \
                      $defaultignore{ }                       \
                      $lvmok{ }                               \
                      lv_name{ home }                         \
                      in_vg { vg00 }                          \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ xfs }     \
                      mountpoint{ /home }                     \
              .

d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true


# Base system
d-i base-installer/kernel/image string linux-image-amd64


# Apt
d-i apt-setup/services-select multiselect security, updates
d-i apt-setup/security_host string security.debian.org


# Package selection
tasksel tasksel/first multiselect standard, ssh-server
popularity-contest popularity-contest/participate boolean false


# Boot loader
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i grub-installer/bootdev  string default


# Finishing up
d-i finish-install/reboot_in_progress note

Espero que os haya servido, un saludo y no useis ChatGPT que os piyarán! :)