Tome la determinación de hacer que mis de mis Raspberries tengan el boot desde la microSD y tener el rootfs sobre iSCSI de un target compartido desde mi NAS (una asignación 1 a 1), considero esto como una mejora al procedimiento del boot sobre NFS, pero esta solución es más compleja también.
Esta solución es más segura (el protocolo iSCSI ademas de poder filtrar por IP permite autenticar con usuario y contraseña).
Encontré información perdigonada en los foros de la fundación Raspberry, pero no encontré nada que este documentado de punta a punta. Quizás si no hubiese hecho andar la solución en NFS, en forma previa, no hubiese tenido el conocimiento acumulado como para llenar los blancos y hacer andar esta.
Preparación de entorno:
Lo primera acción a realizar es descargar la imagen de Ubuntu 20.04 para Raspberry desde la página oficial, una vez finalizada la misma, procedemos a descomprimirla.
En el ejemplo la descarga la hice en el /tmp
cd /tmp unxz ubuntu-20.04-preinstalled-server-arm64+raspi.img.xz
En cada caso adecuar el nombre del archivo en base a la versión que se haya descargado.
Y una vez finalizada la descompresión voy a proceder a montar la imagen para copiar y armar el boot y el / que vamos a utilizar.
Para eso utilizamos la utilidad losetup que nos crea una unidad /dev/loop0 (si ya hay una unidad montada en el loopX lo hará con el siguiente disponible, lo muestra en la salida del comando) con dos particiones, /dev/loop0p1 y /dev/loop0p2 que corresponden al boot y al / respectivamente.
Monto ambas particiones en directorios creados dentro del /tmp
sudo losetup -P -f --show ./ubuntu-20.04-preinstalled-server-arm64+raspi.img mkdir -p /tmp/imgP1 mkdir -p /tmp/imgP2 sudo mount /dev/loop0p1 /tmp/imgP1/ sudo mount /dev/loop0p2 /tmp/imgP2/
PREPARANDO EL ROOTFS BASE:
El siguiente paso es montar la partición / de la imagen para copiarla a la ubicación donde voy a utilizarla como origen para mis instalaciones.
sudo mkdir -p /mnt/storage/rbpi-nfs/base-ub-2004-rootfs sudo rsync -avz ./imgP2/ /mnt/storage/rbpi-nfs/base-ub-2004-rootfs
El comando rsync va a demandar unos minutos. Si no lo tenes instalado, en esta página tenes el set de aplicaciones/utilidades que considero «obligatorias».
Posterior a la copia ejecuto los siguientes comandos para permitir que me pueda conectar como «root» a través del «ssh» utilizando la llave ssh que tengo creada en el sistema.
sudo mkdir -p /mnt/storage/rbpi-nfs/base-ub-2004-rootfs/root/.ssh/ cat ~/.ssh/id_rsa.pub | sudo tee -a /mnt/storage/rbpi-nfs/base-ub-2004-rootfs/root/.ssh/authorized_keys
Preparando el boot base:
En la partición 1 voy a crear un archivo sin vacío con nombre ssh, para que el equipo levante con el servicio SSH habilitado, voy a resguardar el archivo original cmdline.txt y crear uno nuevo con la plantilla de los datos que tengo que cargar.
En este archivo defino la configuración de red en el parámetro «ip=«
ip=<client-ip>:<net-boot-server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
donde:
- client-ip -> es la ip que va a tener la raspberry.
- net-boot-server-ip -> es la ip del servidor de netboot, en este caso no lo usamos y dejamos en valor nulo (::)
- gw-ip -> La ip del gateway de la red
- netmaks -> La máscara de subred, tipicamente 255.255.255.0
- hostname -> El nombre que utilizará nuestra Raspberry.
- device -> el dispositivo que vamos a configurar, en este caso eth0.
- autoconf -> Si habilitamos o deshabilitamos el DHCP en este dispositivo on/off.
En mi caso voy a dejar solo como variable la ip y el nombre de servidor, ya que la el gateway y la mascara de red no van a cambiar.
sudo touch /tmp/imgP1/ssh sudo mv /tmp/imgP1/cmdline.txt /tmp/imgP1/cmdline.ori echo "net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 ISCSI_INITIATOR=\$\$ISCSI_INITIATOR\$\$ ISCSI_TARGET_NAME=\$\$ISCSI_TARGET_NAME\$\$ ISCSI_TARGET_IP=\$\$ISCSI_TARGET_IP\$\$ ISCSI_TARGET_PORT=3260 ISCSI_TARGET_GROUP=1 ISCSI_USERNAME=\$\$ISCSI_USERNAME\$\$ ISCSI_PASSWORD=\$\$ISCSI_PASSWORD\$\$ rw rootfs=ext4 root=UUID=\$\$ISCSI_UUID\$\$ fsck.repair=yes elevator=deadline rootwait fixrtc ip=\$\$CLIENT-IP\$\$::10.0.0.3:255.255.255.0:\$\$HOSTNAME\$\$:eth0:off" | sudo tee -a /tmp/imgP1/cmdline.txt
Finalizada la copia y los trabajos voy a proceder a desmontar las particiones y desacoplar la imagen del sistema.
sudo umount /tmp/imgP1 sudo umount /tmp/imgP2 sudo losetup -d /dev/loop0
Ahora voy a reducir la imagen que descargué de Ubuntu para que contenga solo el boot y reducir su tamaño.
sudo parted ./ubuntu-20.04-preinstalled-server-arm64+raspi.img
En la consola de «parted» ejecutar los comandos delante del #
u #cambiar tipo de unidad de medida b #Configurar unidad en bytes p #Listar particiones rm 2 #Borrar partición 2 (ya habíamos copiado el contenido). quit #Salir de parted
El valor que tomamos es donde termina la primer partición. En este caso «269484031», procedemos a continuación a generar el archivo img del boot en forma estricta. Como los bloque se cortan cada 512B tenemos que cortar la imagen con el mismo criterio.
sudo dd if=./ubuntu-20.04-preinstalled-server-arm64+raspi.img of=./base-ub-2004-boot.img bs=$((((269484031/512)+1)*512)) count=1
Finalizado esto procedo a hacer una copia a la carpeta donde deje los directorios con las fuentes para las nuevas instalaciones.
mv *boot.img /mnt/storage/rbpi-nfs/
En el estado final mi unidad quedo con dos archivos .img y dos directorios con los rootsfs uno de cada para distribución.
Configurando la microSD y el entorno para tener nuestra raspberry con el rootfs en el iSCSI.
Asumo que tenes un servidor iSCSI configurado como lo explico en el tutorial «Configurar iSCSI Storage Server en Ubuntu 20.04» y creaste un destino a tal fin.
Preparando el rootfs sobre ISCSI:
El siguiente paso es refrescar que targets nos expone nuestro iSCSI Storage Server a la ip del cliente. En este caso la ip de mi servidor es la «10.0.0.1«.
sudo iscsiadm -m discovery -t sendtargets -p 10.0.0.1
Para poder establecer la conexión debemos ejecutar los siguientes comandos. Pongo en negrita los datos que son específicos de cada instancia.
sudo iscsiadm --mode node -T alphaprime.sismonda.local:rbpi3-003 -p 10.0.0.1:3260 --op=update --name node.session.auth.authmethod --value=CHAP sudo iscsiadm --mode node -T alphaprime.sismonda.local:rbpi3-003 -p 10.0.0.1:3260 --op=update --name node.session.auth.username --value=Usuario sudo iscsiadm --mode node -T alphaprime.sismonda.local:rbpi3-003 -p 10.0.0.1:3260 --op=update --name node.session.auth.password --value=SuperSecreto sudo iscsiadm --mode node -T alphaprime.sismonda.local:rbpi3-003 -p 10.0.0.1:3260 --login
Para saber que dispositivo fue el asignado para el destino iSCSI podemos ejecutar el siguiente comando:
dmesg |tail -n 11
Como la unidad esta sin formatea proceso a formatearla en ‘ext4‘ y montarla en el directorio ‘/mnt/iSCSI‘. En el proceso de formateo resguardar el valor del UUID le la unidad formteada.
sudo mkfs.ext4 /dev/sdb sudo mkdir -p /mnt/iSCSI sudo mount /dev/sdb /mnt/iSCSI
Verificamos que este montado ejecutando el comando:
mount |grep iSCSI
El siguiente paso a seguir es copiar la estructura base a la unidad que va a ser el «rootfs» de la raspberry.
sudo rsync -avhP /mnt/storage/rbpi-nfs/base-ub-2004-rootfs/ /mnt/iSCSI
Finalizada la clonación del sistema de archivos, voy a proceder a crear un identificador del iniciador iSCSI con un nombre descriptivo para podes distinguir quien consume el recurso desde el iSCSI Storage Server. Resguardar el valor del InitiatorName
echo "InitiatorName=$(iscsi-iname -p rbpi3003)" | sudo tee /mnt/iSCSI/etc/iscsi/initiatorname.iscsi
El último paso es adecuar el fstab para que tome el rootfs con el UUID.
sudo vi /mnt/iSCSI/etc/fstab
Antes:
LABEL=writable / ext4 defaults 0 0 LABEL=system-boot /boot/firmware vfat defaults 0 1
Despues:
UUID=0ba4ce0b-2ed6-4048-b2ac-9a980a985a1e / ext4 defaults 0 0 LABEL=system-boot /boot/firmware vfat defaults 0 1
Con esto podemos dar por terminada la perapración de nuestro rootfs sobre iSCSI y procedemos a desmontar y desvincular la unidad iSCSI.
sudo umount /mnt/iSCSI sudo iscsiadm --mode node -T alphaprime.sismonda.local:rbpi3-003 -p 10.0.0.1:3260 -u sudo iscsiadm --mode node -T alphaprime.sismonda.local:rbpi3-003 -p 10.0.0.1:3260 -o delete
Preparación del boot en la microSD:
A continuación procedemos a preparar la microSD. La conectamos al equipo con nuestro lector preferido y verificamos que unidad es la asignada.
dmesg |tail
En este caso mi MicroSD es el dispositivo /dev/sdb (revisar y estar seguro que es el mismo en el caso de ustedes, caso contrario adecuar porque sino van a romper algo).
sudo dd if=/mnt/storage/rbpi-nfs/base-ub-2004-boot.img of=/dev/sdb bs=4M status=progress
Procedo a montarla para poder adecuar los archivos para el booteo por iSCSI.
sudo mkdir -p /tmp/sdb1/ sudo mount /dev/sdb1 /tmp/sdb1/
Ahora tengo que modificar el archivo «cmdline.txt«. Este archivo contiene una sola línea, por favor revisen que en la edición no se escape ningún salto de línea.
sudo vi /tmp/sdb1/cmdline.txt
Antes de editar el «cmdline.txt«:
net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 ISCSI_INITIATOR=$$ISCSI_INITIATOR$$ ISCSI_TARGET_NAME=$$ISCSI_TARGET_NAME$$ ISCSI_TARGET_IP=$$ISCSI_TARGET_IP$$ ISCSI_TARGET_PORT=3260 ISCSI_TARGET_GROUP=1 ISCSI_USERNAME=$$ISCSI_USERNAME$$ ISCSI_PASSWORD=$$ISCSI_PASSWORD$$ rw rootfs=ext4 root=UUID=$$ISCSI_UUID$$ fsck.repair=yes elevator=deadline rootwait fixrtc ip=$$CLIENT-IP$$::10.0.0.3:255.255.255.0:$$HOSTNAME$$:eth0:off
Y adecuar los datos por:
$$ISCSI_INITIATOR$$ -> rbpi3003:a22c632eb8a
$$ISCSI_TARGET_NAME$$ -> alphaprime.sismonda.local:rbpi3-003
$$ISCSI_TARGET_IP$$ -> 10.0.0.1
$$ISCSI_USERNAME$$ -> Usuario
$$ISCSI_PASSWORD$$ -> SuperSecreto
$$ISCSI_UUID$$ -> 0ba4ce0b-2ed6-4048-b2ac-9a980a985a1e
$$CLIENT-IP$$ -> 10.0.0.33
$$HOSTNAME$$ -> rbpi3-003
Después DE EDITAR EL «CMDLINE.TXT«:
net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 ISCSI_INITIATOR=rbpi3003:a22c632eb8a ISCSI_TARGET_NAME=alphaprime.sismonda.local:rbpi3-003 ISCSI_TARGET_IP=10.0.0.1 ISCSI_TARGET_PORT=3260 ISCSI_TARGET_GROUP=1 ISCSI_USERNAME=Usuario ISCSI_PASSWORD=SuperSecreto rw rootfs=ext4 root=UUID=0ba4ce0b-2ed6-4048-b2ac-9a980a985a1e fsck.repair=yes elevator=deadline rootwait fixrtc ip=10.0.0.33::10.0.0.3:255.255.255.0:rbpi3-003:eth0:off
finalizada la edición del archivo, se debe desmontar la tarjeta microSD y ponerla en la raspberry, conectar la red y después darle energía.
sudo umount /dev/sdb1
Ya en nuestra Raspberry con rootfs sobre ISCSI :
Renombre de usuario por defecto:
Ya que entramos como root, vamos a cambiar el usuario «ubuntu» / «pi» por uno de uso personal. Esto lo hacemos ejecutando los siguientes comandos:
usermod -md /home/NuevoUsuario -l NuevoUsuario ubuntu usermod -c "Nuevo nombre apellido" NuevoUsuario groupmod -n NuevoUsuario ubuntu
También podemos proceder a cambiar al contraseña del nuevo usuario, esto se realiza ejecutando el comando:
passwd NuevoUsuario
Ahora podemos salir del equipo y volver a ingresar con un usuario terrenal y dejar el root.
CONFIGURACIÓN DE ZONA HORARIA:
Por defecto Ubuntu vienen configurados en GTM 0. Esto discrepa con la configuración regional de mi residencia.
sudo dpkg-reconfigure tzdata
Con estos paso ya tenemos el sistema en fecha y mostrando la hora local.
Configuración de hostname / nombre de servidor:
Para que nos muestre el prompt el nombre que le asignamos al equipo. Para que impacte el cambio debemos salir y volver a entrar al equipo.
sudo hostnamectl set-hostname rbpi3-003
Configurar DNS:
Como en la configuración de red que usamos no se puede especificar el dns, vamos a configurar los mismos en el archivo «/etc/systemd/resolved.conf«.
sudo vi /etc/systemd/resolved.conf
Y edito las líneas en negrita. Adecuar los valores según la configuración de la red donde están.
[Resolve] DNS=10.0.0.10 10.0.0.31 10.0.0.62 #FallbackDNS= Domains=sismonda.local #LLMNR=no #MulticastDNS=no #DNSSEC=no #DNSOverTLS=no #Cache=yes #DNSStubListener=yes #ReadEtcHosts=yes
Finalizada la edición debemos reiniciar el servicio para que aplique los cambios.
sudo systemctl restart systemd-resolved
Opcionales:
Si instalaste en entorno gráfico seguramente se van a aplicar los perfiles de ahorro de enrgía, me paso que la Raspberry dejaba de funcionar cuando la dejaba de usar después de 20/30 minutos. Para evitar esto debemos proceder a deshabilitar la función de hibernación del Ubuntu.
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
Si por algún motivo lo queremos volver a activar, podemos hacerlo ejecutando.
sudo systemctl unmask sleep.target suspend.target hibernate.target hybrid-sleep.target