diff --git a/.gitignore b/.gitignore index b9aa2fd..69029b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ iso settings.ini -# ignore all possible snapshots in this dir +# ignore all possible snapshots in this repo *.json diff --git a/README-es.md b/README-es.md index a648bb5..b1b4255 100644 --- a/README-es.md +++ b/README-es.md @@ -54,3 +54,9 @@ OPCIONES ## Enfoque workbench-script trata de ser simple y minimalista, una función principal y funciones de soporte la lectura de las diferentes funcionalidades. + +## Generar ISO para el USB + +Para generar la iso y preparar un usb que arranque con workbench necesitas generarte una workbench de este, con tu configuración específica + +Ejecuta `./deploy-workbench.sh` diff --git a/deploy-workbench.sh b/deploy-workbench.sh index ffa4cdc..a0e4d79 100755 --- a/deploy-workbench.sh +++ b/deploy-workbench.sh @@ -34,12 +34,12 @@ END create_iso() { # Copy kernel and initramfs - vmlinuz="$(ls -1v ${ISO_PATH}/chroot/boot/vmlinuz-* | tail -n 1)" - initrd="$(ls -1v ${ISO_PATH}/chroot/boot/initrd.img-* | tail -n 1)" - ${SUDO} cp ${vmlinuz} ${ISO_PATH}/staging/live/vmlinuz - ${SUDO} cp ${initrd} ${ISO_PATH}/staging/live/initrd + vmlinuz="$(ls -1v "${ISO_PATH}"/chroot/boot/vmlinuz-* | tail -n 1)" + initrd="$(ls -1v "${ISO_PATH}"/chroot/boot/initrd.img-* | tail -n 1)" + ${SUDO} cp ${vmlinuz} "${ISO_PATH}"/staging/live/vmlinuz + ${SUDO} cp ${initrd} "${ISO_PATH}"/staging/live/initrd # Creating ISO - iso_path="${ISO_PATH}/${iso_name}.iso" + iso_path=""${ISO_PATH}"/${iso_name}.iso" # 0x14 is FAT16 Hidden FAT16 <32, this is the only format detected in windows10 automatically when using a persistent volume of 10 MB ${SUDO} xorrisofs \ @@ -59,7 +59,7 @@ create_iso() { -e /EFI/boot/efiboot.img \ -no-emul-boot \ -isohybrid-gpt-basdat \ - -append_partition 2 0xef ${ISO_PATH}/staging/EFI/boot/efiboot.img \ + -append_partition 2 0xef "${ISO_PATH}"/staging/EFI/boot/efiboot.img \ -append_partition 3 0x14 "${rw_img_path}" \ "${ISO_PATH}/staging" @@ -138,7 +138,7 @@ EOF ${SUDO} grub-mkstandalone \ --format=x86_64-efi \ - --output=${ISO_PATH}/tmp/bootx64.efi \ + --output="${ISO_PATH}"/tmp/bootx64.efi \ --locales="" \ --fonts="" \ "boot/grub/grub.cfg=${ISO_PATH}/tmp/grub-standalone.cfg" @@ -149,10 +149,10 @@ EOF # grubx64 looks for a file in /EFI/debian/grub.cfg -> src src https://unix.stackexchange.com/questions/648089/uefi-grub-not-finding-config-file ${SUDO} cp /usr/lib/shim/shimx64.efi.signed /tmp/bootx64.efi ${SUDO} cp /usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed /tmp/grubx64.efi - ${SUDO} cp ${ISO_PATH}/tmp/grub-standalone.cfg ${ISO_PATH}/staging/EFI/debian/grub.cfg + ${SUDO} cp "${ISO_PATH}/tmp/grub-standalone.cfg" "${ISO_PATH}/staging/EFI/debian/grub.cfg" ( - cd ${ISO_PATH}/staging/EFI/boot + cd "${ISO_PATH}/staging/EFI/boot" ${SUDO} dd if=/dev/zero of=efiboot.img bs=1M count=20 ${SUDO} mkfs.vfat efiboot.img ${SUDO} mmd -i efiboot.img efi efi/boot @@ -178,8 +178,8 @@ compress_chroot_dir() { # why squashfs -> https://unix.stackexchange.com/questions/163190/why-do-liveusbs-use-squashfs-and-similar-file-systems # noappend option needed to avoid this situation -> https://unix.stackexchange.com/questions/80447/merging-preexisting-source-folders-in-mksquashfs ${SUDO} mksquashfs \ - ${ISO_PATH}/chroot \ - ${ISO_PATH}/staging/live/filesystem.squashfs \ + "${ISO_PATH}/chroot" \ + "${ISO_PATH}/staging/live/filesystem.squashfs" \ ${DEBUG_SQUASHFS_ARGS:-} \ -noappend -e boot } @@ -198,8 +198,13 @@ create_persistence_partition() { ${SUDO} umount -f -l "${tmp_rw_mount}" >/dev/null 2>&1 || true mkdir -p "${tmp_rw_mount}" ${SUDO} mount "$(pwd)/${rw_img_path}" "${tmp_rw_mount}" - ${SUDO} mkdir -p "${tmp_rw_mount}/settings" - ${SUDO} cp -v settings.ini "${tmp_rw_mount}/settings/settings.ini" + ${SUDO} mkdir -p "${tmp_rw_mount}" + if [ -f "settings.ini" ]; then + ${SUDO} cp -v settings.ini "${tmp_rw_mount}/settings.ini" + else + echo "ERROR: settings.ini does not exist yet, cannot read config from there. You can take inspiration with file settings.ini.example" + exit 1 + fi ${SUDO} umount "${tmp_rw_mount}" uuid="$(blkid "${rw_img_path}" | awk '{ print $3; }')" @@ -258,14 +263,32 @@ prepare_app() { # startup script execution cat > "${ISO_PATH}/chroot/root/.profile" < "${ISO_PATH}/chroot/root/.bash_history" < extra src https://wiki.debian.org/SecureBoot/ # -> extra src https://wiki.debian.org/SecureBoot/VirtualMachine @@ -423,17 +445,17 @@ install_requirements() { # thanks https://willhaley.com/blog/custom-debian-live-environment/ create_base_dirs() { - mkdir -p ${ISO_PATH} - mkdir -p ${ISO_PATH}/staging/EFI/boot - mkdir -p ${ISO_PATH}/staging/boot/grub/x86_64-efi - mkdir -p ${ISO_PATH}/staging/isolinux - mkdir -p ${ISO_PATH}/staging/live - mkdir -p ${ISO_PATH}/tmp + mkdir -p "${ISO_PATH}" + mkdir -p "${ISO_PATH}/staging/EFI/boot" + mkdir -p "${ISO_PATH}/staging/boot/grub/x86_64-efi" + mkdir -p "${ISO_PATH}/staging/isolinux" + mkdir -p "${ISO_PATH}/staging/live" + mkdir -p "${ISO_PATH}/tmp" # usb name - ${SUDO} touch ${ISO_PATH}/staging/${iso_name} + ${SUDO} touch "${ISO_PATH}/staging/${iso_name}" # for uefi secure boot grub config file - mkdir -p ${ISO_PATH}/staging/EFI/debian + mkdir -p "${ISO_PATH}/staging/EFI/debian" } # this function is used both in shell and chroot diff --git a/pxe/.env.example b/pxe/.env.example new file mode 100644 index 0000000..8f80779 --- /dev/null +++ b/pxe/.env.example @@ -0,0 +1,4 @@ +server_ip=192.168.1.2 +nfs_allowed_lan=192.168.1.0/24 +tftp_path='/srv/pxe-tftp' +nfs_path='/srv/pxe-nfs' diff --git a/pxe/.gitignore b/pxe/.gitignore new file mode 100644 index 0000000..9f6d6c8 --- /dev/null +++ b/pxe/.gitignore @@ -0,0 +1,2 @@ +.env +pxe-menu.cfg diff --git a/pxe/Makefile b/pxe/Makefile new file mode 100644 index 0000000..edf648f --- /dev/null +++ b/pxe/Makefile @@ -0,0 +1,2 @@ +test_pxe: + qemu-system-x86_64 -m 1G -boot n -netdev user,id=mynet0,tftp=/srv/pxe-tftp,bootfile=pxelinux.0 -device e1000,netdev=mynet0 diff --git a/pxe/README-en.md b/pxe/README-en.md new file mode 100644 index 0000000..1333ed7 --- /dev/null +++ b/pxe/README-en.md @@ -0,0 +1 @@ +TODO diff --git a/pxe/README-es.md b/pxe/README-es.md new file mode 100644 index 0000000..c1cda36 --- /dev/null +++ b/pxe/README-es.md @@ -0,0 +1,55 @@ +# workbench via PXE + +## Introducción + +Permite arrancar workbench a través de la red en vez de por USB. Utiliza la misma imagen generada por el script [deploy-workbench.sh](../deploy-workbench.sh), pero en el formato compatible con el arranque por red en vez de la iso. + +Ejecuta el siguiente script en un servidor debian estable que estará dedicado a la gestión del pxe server + +``` +./install-pxe.sh +``` + +Este servidor aporta un servicio de arranque por red tipo PXE, y no hace colisión con un servidor DHCP existente. + +## Funcionamiento + +El servidor PXE ofrece a la máquina que arranca un *debian live* a través de [NFS](https://es.wikipedia.org/wiki/Network_File_System). Una vez arrancado, ejecuta el `workbench-script.py` con la configuración remota del servidor PXE. Cuando ha terminado, también guarda en el mismo servidor PXE el snapshot resultante. También lo puede guardar en devicehub si se especifica en la variable `url` de la configuración `settings.ini`. + +## Probarlo todo en localhost + +Preparar configuración de `.env` tal como: + +``` +server_ip=10.0.2.2 +nfs_allowed_lan=10.0.2.0/24 +tftp_path='/srv/pxe-tftp' +nfs_path='/srv/pxe-nfs' +``` + +Red y host 10.0.2.2? Esta es la forma en que el programa *qemu* hace red en localhost, 10.0.2.2 es la dirección de localhost que saliendo de qemu es traducida como 127.0.0.1 + +Desplegar servidores TFTP y NFS en el mismo ordenador, para permitir nfs inseguro: + +``` +DEBUG=true ./install-pxe.sh +``` + +Los directorios inseguros contienen configuración y snapshots de workbench, nada importante supongo. Aún así, `DEBUG=true` no se recomienda para un entorno de producción para evitar sorpresas. + + +Y para terminar, probar el cliente PXE con el siguiente comando: + +``` +make test_pxe +``` + +## Recursos + +El servicio PXE + +- Originalmente inspirado en este artículo https://farga.exo.cat/exo/wiki/src/branch/master/howto/apu/apu-installer.md +- https://github.com/eReuse/workbench-live/blob/feature/pxe/docs/PXE-setup.md +- https://wiki.debian.org/PXEBootInstall +- https://wiki.debian.org/DebianInstaller/NetbootFirmware +- [In this presentation](https://people.debian.org/~andi/LiveNetboot.pdf), recomienda página 12 [4.6 Building a netboot image](https://live-team.pages.debian.net/live-manual/html/live-manual/the-basics.en.html#236) [4.7 Webbooting](https://live-team.pages.debian.net/live-manual/html/live-manual/the-basics.en.html#275) diff --git a/pxe/README.md b/pxe/README.md new file mode 100644 index 0000000..9f75404 --- /dev/null +++ b/pxe/README.md @@ -0,0 +1,5 @@ +# pxe + +- [Español](./README-es.md) +- [English](./README-en.md) + diff --git a/pxe/install-pxe.sh b/pxe/install-pxe.sh new file mode 100755 index 0000000..ee2fdd9 --- /dev/null +++ b/pxe/install-pxe.sh @@ -0,0 +1,158 @@ +#!/bin/sh + +# Copyright (c) 2024 Pedro +# SPDX-License-Identifier: AGPL-3.0-or-later + +set -e +set -u +# DEBUG +set -x + +detect_user() { + userid="$(id -u)" + # detect non root user without sudo + if [ ! "${userid}" = 0 ] && id ${USER} | grep -qv sudo; then + echo "ERROR: this script needs root or sudo permissions (current user is not part of sudo group)" + exit 1 + # detect user with sudo or already on sudo src https://serverfault.com/questions/568627/can-a-program-tell-it-is-being-run-under-sudo/568628#568628 + elif [ ! "${userid}" = 0 ] || [ -n "${SUDO_USER}" ]; then + SUDO='sudo' + # jump to current dir where the script is so relative links work + cd "$(dirname "${0}")" + # working directory to build the iso + ISO_PATH="iso" + # detect pure root + elif [ "${userid}" = 0 ]; then + SUDO='' + ISO_PATH="/opt/workbench" + fi +} + +install_dependencies() { + ${SUDO} apt update + ${SUDO} apt install -y wget dnsmasq nfs-kernel-server rsync syslinux +} + +backup_file() { + target="${1}" + ts="$(date +'%Y-%m-%d_%H-%M-%S')" + + if [ -f "${target}" ]; then + if ! grep -q 'we should do a backup' "${target}"; then + ${SUDO} cp -a "${target}" "${target}-bak_${ts}" + fi + fi +} + +install_nfs() { + # append live directory, which is expected by the debian live env + ${SUDO} mkdir -p "${nfs_path}/live" + ${SUDO} mkdir -p "${nfs_path}/snapshots" + + # debian live nfs path is readonly, do a trick + # to make snapshots subdir readwrite + if ! grep -q "/snapshots" /proc/mounts; then + ${SUDO} mkdir -p "/snapshots" + ${SUDO} mount --bind "${nfs_path}/snapshots" "/snapshots" + fi + + backup_file /etc/exports + + if [ "${DEBUG:-}" ]; then + nfs_debug=' 127.0.0.1(rw,sync,no_subtree_check,no_root_squash,insecure)' + fi + + ${SUDO} tee /etc/exports <