From f635e7010c5b7b4212f286cc2892cadfbafd6bbb Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Fri, 1 Sep 2023 15:41:56 -0400 Subject: [PATCH] Replace old buildiso.sh with live-build script The old script was cumbersome and complex. Replace it with a script that leverages the Debian live-build (lb) framework to simplify the script and configuration as well as minimize sprawl in the final image (~40MB savings). --- buildiso.sh | 251 +++++++++++++++++++--------------------------------- 1 file changed, 89 insertions(+), 162 deletions(-) diff --git a/buildiso.sh b/buildiso.sh index 5aa1f2c..80a5b58 100755 --- a/buildiso.sh +++ b/buildiso.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Generate a PVC autoinstaller ISO +# Generate a PVC autoinstaller ISO via live-build # This ISO makes a number of assumptions about the system and asks # minimal questions in order to streamline the install process versus @@ -12,14 +12,8 @@ fail() { exit 1 } -fail="" -which debootstrap &>/dev/null || fail="y" -which mksquashfs &>/dev/null || fail="y" -which xorriso &>/dev/null || fail="y" -test -f /usr/lib/ISOLINUX/isohdpfx.bin &>/dev/null || fail="y" -if [[ -n ${fail} ]]; then - fail "This script requires debootstrap, xorriso, squashfs-tools, and isolinux" -fi +which lb &>/dev/null || fail "This script requires live-build" +sudo -n true &>/dev/null || fail "The user running this script must have sudo privileges." isofilename="pvc-installer_$(date +%Y-%m-%d).iso" deployusername="deploy" @@ -27,26 +21,18 @@ deployusername="deploy" show_help() { echo -e "PVC install ISO generator" echo - echo -e " Generates a mostly-automated installer ISO for a PVC node base system. The ISO" - echo -e " boots, then runs 'install.sh' to perform the installation to a target server." - echo -e " This script prompts for a few questions on startup to configure the system, then" - echo -e " performs the remaining installation to PVC node specifications unattended," - echo -e " including configuring networking on the selected interface, wiping the selected" - echo -e " disk, partitioning, installing the base OS, and performing some initial" - echo -e " configuration to allow the PVC Ansible role to take over after completion." + echo -e " Generates a mostly-automated installer ISO for a PVC node base system via lb." echo - echo -e "Usage: $0 [-h] [-o ] [-s ] [-a] [-u username]" + echo -e "Usage: $0 [-h] [-o ] [-u username] [-a]" echo echo -e " -h: Display this help message." echo -e " -o: Create the ISO as instead of the default." - echo -e " -s: Obtain the source Debian Live ISO from instead of" - echo -e " the default." - echo -e " -a: Use cached squashfs artifact during rebuild (cached ISO and debootstrap" - echo -e " artifacts are always used)." echo -e " -u: Change 'deploy' user to a new username." + echo -e " -a: Preserve live-build artifacts." + echo -e " -k: Preserve live-build config." } -while getopts "h?o:s:au:" opt; do +while getopts "h?o:u:ak" opt; do case "$opt" in h|\?) show_help @@ -55,161 +41,102 @@ while getopts "h?o:s:au:" opt; do o) isofilename=$OPTARG ;; - s) - srcliveisourl=$OPTARG - ;; - a) - usecachedsquashfs='y' - ;; u) deployusername=$OPTARG ;; + a) + preserve_artifacts='y' + ;; + k) + preserve_livebuild='y' + ;; esac done -srcliveisopath="https://cdimage.debian.org/mirror/cdimage/release/current-live/amd64/iso-hybrid" -srcliveisofilename="$( wget -O- ${srcliveisopath}/ 2>/dev/null | grep 'debian-live-.*-amd64-standard.iso' | awk -F '"' '{ print $6 }' )" -srcliveisourl="${srcliveisopath}/${srcliveisofilename}" -srcliveisofile="$( basename ${srcliveisourl} )" +PACKAGE_LIST_MAIN="live-tools linux-image-amd64 mdadm lvm2 parted gdisk debootstrap grub-pc-bin grub-efi-amd64 sipcalc vim ca-certificates vlan" +PACKAGE_LIST_NONFREE="firmware-bnx2 firmware-bnx2x" -tempdir=$( mktemp -d ) +mkdir -p artifacts/lb +pushd artifacts/lb -cleanup() { - echo -n "Cleaning up... " - sudo rm -rf ${tempdir} &>/dev/null - echo "done." - echo -} +# Initialize the live-build config +lb config --distribution buster --architectures amd64 --archive-areas "main contrib non-free" --apt-recommends false -fail() { - echo $@ - cleanup - exit 1 -} +# Configure the "standard" live task (no GUI) +echo "live-task-standard" > config/package-lists/desktop.list.chroot -prepare_iso() { - echo -n "Creating temporary directories... " - if [[ ! -d artifacts ]]; then - mkdir artifacts &>/dev/null || fail "Error creating artifacts directory." - fi - mkdir ${tempdir}/rootfs/ ${tempdir}/installer/ &>/dev/null || fail "Error creating temporary directories." - echo "done." +# Add additional live packages +echo ${PACKAGE_LIST_MAIN} > config/package-lists/installer.list.chroot +echo ${PACKAGE_LIST_NONFREE} > config/package-lists/nonfree.list.chroot - echo -n "Downloading Debian Live ISO... " - if [[ ! -f artifacts/${srcliveisofile} ]]; then - wget -O artifacts/${srcliveisofile} ${srcliveisourl} &>/dev/null || { rm -f artifacts/${srcliveisofile}; fail "Error downloading source ISO."; } - echo "done." - else - echo "using cached file 'artifacts/${srcliveisofile}'." - fi +# Add root password hook +mkdir -p config/includes.chroot/lib/live/config/ +cat < config/includes.chroot/lib/live/config/2000-remove-root-pw +#!/bin/sh +echo "I: remove root password" +passwd --delete root +EOF +chmod +x config/includes.chroot/lib/live/config/2000-remove-root-pw - echo -n "Extracting Debian Live ISO files... " - iso_tempdir=$( mktemp -d ) - sudo mount artifacts/${srcliveisofile} ${iso_tempdir} &>/dev/null || fail "Error mounting Live ISO file." - sudo rsync -a --exclude live/filesystem.squashfs --exclude isolinux/menu.cfg --exclude isolinux/stdmenu.cfg ${iso_tempdir}/ ${tempdir}/installer/ &>/dev/null || fail "Error extracting Live ISO files." - sudo umount ${iso_tempdir} &>/dev/null || fail "Error unmounting Live ISO file." - rmdir ${iso_tempdir} &>/dev/null - echo "done." -} +# Set root bashrc +mkdir -p config/includes.chroot/root +echo "/install.sh" > config/includes.chroot/root/.bashrc -prepare_rootfs() { - echo -n "Preparing Debian live installation via debootstrap... " - SQUASHFS_PKGLIST="mdadm,lvm2,parted,gdisk,debootstrap,grub-pc,grub-efi-amd64,linux-image-amd64,sipcalc,live-boot,dosfstools,vim,ca-certificates,vlan" - if [[ ! -d artifacts/debootstrap ]]; then - sudo mkdir -p artifacts/debootstrap/var/cache/apt/archives &>/dev/null - clean_me="y" - sudo mount --bind /var/cache/apt/archives artifacts/debootstrap/var/cache/apt/archives &>/dev/null && clean_me="" - sudo /usr/sbin/debootstrap \ - --include=${SQUASHFS_PKGLIST} \ - buster \ - artifacts/debootstrap/ \ - http://ftp.ca.debian.org/debian &>debootstrap.log || fail "Error performing debootstrap." - # Grab some additional files in non-free - sudo wget http://ftp.ca.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-bnx2_20190114-2_all.deb -O artifacts/debootstrap/var/cache/apt/archives/firmware-bnx2_20190114-2_all.deb - sudo chroot artifacts/debootstrap/ dpkg -i /var/cache/apt/archives/firmware-bnx2_20190114-2_all.deb || fail "Error installing supplemental package firmware-bnx2" - sudo wget http://ftp.ca.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-bnx2x_20190114-2_all.deb -O artifacts/debootstrap/var/cache/apt/archives/firmware-bnx2x_20190114-2_all.deb - sudo chroot artifacts/debootstrap/ dpkg -i /var/cache/apt/archives/firmware-bnx2x_20190114-2_all.deb || fail "Error installing supplemental package firmware-bnx2x" - if [[ -n ${clean_me} ]]; then - sudo chroot artifacts/debootstrap/ apt clean &>/dev/null || fail "Error cleaning apt cache in debootstrap." - else - sudo umount artifacts/debootstrap/var/cache/apt/archives &>/dev/null - fi - sudo rsync -au artifacts/debootstrap/ ${tempdir}/rootfs/ &>/dev/null || fail "Error copying debootstrap to tempdir." - echo "done." - else - sudo rsync -au artifacts/debootstrap/ ${tempdir}/rootfs/ &>/dev/null || fail "Error copying debootstrap to tempdir." - echo "using cached debootstrap 'artifacts/debootstrap'." - fi - - echo -n "Configuring Debian live installation... " - sudo cp -a artifacts/debootstrap/boot/vmlinuz* ${tempdir}/installer/live/vmlinuz &>/dev/null || fail "Error copying kernel." - sudo cp -a artifacts/debootstrap/boot/initrd.img* ${tempdir}/installer/live/initrd.img &>/dev/null || fail "Error copying initrd." - sudo cp ${tempdir}/rootfs/lib/systemd/system/getty\@.service ${tempdir}/rootfs/etc/systemd/system/getty@tty1.service &>/dev/null || fail "Error copying getty override to tempdir." - sudo sed -i 's|/sbin/agetty|/sbin/agetty --autologin root|g' \ - ${tempdir}/rootfs/etc/systemd/system/getty@tty1.service &>/dev/null || fail "Error setting autologin in getty override." - sudo tee ${tempdir}/rootfs/etc/hostname <<<"pvc-node-installer" &>/dev/null || fail "Error setting hostname." - sudo tee ${tempdir}/rootfs/etc/resolv.conf <<<"nameserver 8.8.8.8" &>/dev/null || fail "Error setting resolv.conf" - sudo tee -a ${tempdir}/rootfs/root/.bashrc <<<"/install.sh" &>/dev/null || fail "Error setting bashrc." - sudo chroot ${tempdir}/rootfs/ /usr/bin/passwd -d root &>/dev/null || fail "Error disabling root password." - sudo cp install.sh ${tempdir}/rootfs/ &>/dev/null || fail "Error copying install.sh to tempdir." - sudo sed -i "s/XXISOXX/${isofilename}/g" ${tempdir}/rootfs/install.sh &>/dev/null || fail "Error editing install.sh script." - sudo sed -i "s/XXDEPLOYUSERXX/${deployusername}/g" ${tempdir}/rootfs/install.sh &>/dev/null || fail "Error editing install.sh script." - echo "done." - - echo -n "Generating squashfs image of live installation... " - if [[ ! -f artifacts/filesystem.squashfs || -z ${usecachedsquashfs} ]]; then - if [[ -f artifacts/filesystem.squashfs ]]; then - rm -f artifacts/filesystem.squashfs &>/dev/null - fi - sudo nice mksquashfs ${tempdir}/rootfs/ artifacts/filesystem.squashfs -e boot &>/dev/null || fail "Error generating squashfs." - sudo rsync -a artifacts/filesystem.squashfs ${tempdir}/installer/live/filesystem.squashfs &>/dev/null || fail "Error copying squashfs to tempdir." - echo "done." - else - sudo rsync -a artifacts/filesystem.squashfs ${tempdir}/installer/live/filesystem.squashfs &>/dev/null || fail "Error copying squashfs to tempdir." - echo "using cached squashfs 'artifacts/filesystem.squashfs'." - fi -} +# Set hostname and resolv.conf +mkdir -p config/includes.chroot/etc +echo "pvc-live-installer" > config/includes.chroot/etc/hostname +echo "nameserver 8.8.8.8" > config/includes.chroot/etc/resolv.conf -build_iso() { - echo -n "Copying live boot configurations... " - sudo cp -a grub.cfg ${tempdir}/installer/boot/grub/grub.cfg &>/dev/null || fail "Error copying grub.cfg file." - sudo cp -a theme.txt ${tempdir}/installer/boot/grub/theme.txt &>/dev/null || fail "Error copying theme.txt file." - sudo cp -a isolinux.cfg ${tempdir}/installer/isolinux/isolinux.cfg &>/dev/null || fail "Error copying isolinux.cfg file." - sudo cp -a splash.png ${tempdir}/installer/splash.png &>/dev/null || fail "Error copying splash.png file." - echo "done." +# Set single vty +mkdir -p config/includes.chroot/etc/systemd/ +cat < config/includes.chroot/etc/systemd/logind.conf +[Login] +NAutoVTs=2 +EOF - echo -n "Creating LiveCD ISO... " - pushd ${tempdir}/installer &>/dev/null - xorriso \ - -as mkisofs \ - -iso-level 3 \ - -o ../${isofilename} \ - -full-iso9660-filenames \ - -volid "PVC_NODE_INSTALLER" \ - -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin \ - -eltorito-boot \ - isolinux/isolinux.bin \ - -no-emul-boot \ - -boot-load-size 4 \ - -boot-info-table \ - --eltorito-catalog isolinux/isolinux.cat \ - -eltorito-alt-boot \ - -e boot/grub/efi.img \ - -no-emul-boot \ - -isohybrid-gpt-basdat \ - -append_partition 2 0xef boot/grub/efi.img \ - . &>/dev/null || fail "Error creating ISO file." - popd &>/dev/null - echo "done." +mkdir -p config/includes.chroot/etc/systemd/system/getty@.service.d +cat < config/includes.chroot/etc/systemd/system/getty@.service.d/override.conf +[Service] +ExecStart= +ExecStart=-/sbin/agetty -o '-p -- \\\u' --autologin root --noclear %I \$TERM +EOF - echo -n "Moving generated ISO to './${isofilename}'... " - mv -f ${tempdir}/${isofilename} ${isofilename} &>/dev/null || fail "Error moving ISO file." - echo "done." -} +mkdir -p config/includes.chroot/etc/systemd/system/serial-getty@.service.d +cat < config/includes.chroot/etc/systemd/system/serial-getty@.service.d/override.conf +[Service] +ExecStart= +ExecStart=-/sbin/agetty -o '-p -- \\\u' --autologin root --noclear --keep-baud 115200,38400,9600 %I \$TERM +EOF -prepare_iso -prepare_rootfs -build_iso -cleanup +# Install GRUB config, theme, and splash +mkdir -p config/includes.chroot/boot/grub +cp ../../grub.cfg config/includes.chroot/boot/grub/grub.cfg +cp ../../theme.txt config/includes.chroot/boot/grub/theme.txt +cp ../../splash.png config/includes.chroot/splash.png + +# Install install.sh script +cp ../../install.sh config/includes.chroot/install.sh +chmod +x config/includes.chroot/install.sh + +# Customize install.sh script +sed -i "s/XXDATEXX/$(date)/g" config/includes.chroot/install.sh +sed -i "s/XXDEPLOYUSERXX/${deployusername}/g" config/includes.chroot/install.sh + +# Build the live image +sudo lb build + +# Move the ISO image out +cp live-image-amd64.hybrid.iso ../../${isofilename} + +# Clean up the artifacts +if [[ -z ${preserve_artifacts} ]]; then + sudo lb clean +fi + +popd + +# Clean up the config +if [[ -z ${preserve_livebuild} ]]; then + sudo rm -rf artifacts/lb +fi -echo "PVC Live Installer ISO generation complete."