Harden cloud-init disable and rebuild ISO properly in build-usb
Autoinstall user-data now disables cloud-init in multiple stages (late-commands + runcmd + systemd masks) to prevent post-install hangs. Also disables networkd-wait-online for air-gapped networks. build-usb.sh switched from in-place ISO patching to full extract and rebuild with xorriso mkisofs for reliable UEFI boot. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -35,7 +35,7 @@ autoinstall:
|
|||||||
identity:
|
identity:
|
||||||
hostname: pxeserver
|
hostname: pxeserver
|
||||||
username: pxe
|
username: pxe
|
||||||
password: "$6$rounds=656000$TpsuBw0N85085mpx$KtKsCwFlowg4NY41gUqx5ljef8cJ8uPFfgg43MyCPWByfXkhM5XushcdtkNps6lKeQFQZtli/QU.s52AUc7XC."
|
password: '$6$8AerqUockJh6ycgl$HJFBYjiFqXpzgcU9edto4CMrnaDpEX71Epin.kNTpj57GVjimIDHhcQs0AC4tmkEkKUaj.S/55wsBfMsV0KC71'
|
||||||
|
|
||||||
# Enable SSH
|
# Enable SSH
|
||||||
ssh:
|
ssh:
|
||||||
@@ -44,7 +44,7 @@ autoinstall:
|
|||||||
|
|
||||||
# Installer-stage late commands
|
# Installer-stage late commands
|
||||||
late-commands:
|
late-commands:
|
||||||
# Install deb packages from CIDATA USB
|
# Install deb packages from CIDATA USB, then disable cloud-init
|
||||||
- |
|
- |
|
||||||
curtin in-target --target=/target -- bash -c '
|
curtin in-target --target=/target -- bash -c '
|
||||||
mkdir -p /mnt/cidata
|
mkdir -p /mnt/cidata
|
||||||
@@ -61,11 +61,25 @@ autoinstall:
|
|||||||
fi
|
fi
|
||||||
umount /mnt/cidata
|
umount /mnt/cidata
|
||||||
fi
|
fi
|
||||||
|
# Disable cloud-init AFTER dpkg (dpkg may overwrite earlier disables)
|
||||||
|
mkdir -p /etc/cloud
|
||||||
|
touch /etc/cloud/cloud-init.disabled
|
||||||
|
ln -sf /dev/null /etc/systemd/system/cloud-init.service
|
||||||
|
ln -sf /dev/null /etc/systemd/system/cloud-init-local.service
|
||||||
|
ln -sf /dev/null /etc/systemd/system/cloud-config.service
|
||||||
|
ln -sf /dev/null /etc/systemd/system/cloud-final.service
|
||||||
|
ln -sf /dev/null /etc/systemd/system/cloud-init.target
|
||||||
|
# Disable networkd-wait-online (no gateway on air-gapped network, causes 2min hang)
|
||||||
|
ln -sf /dev/null /etc/systemd/system/systemd-networkd-wait-online.service
|
||||||
'
|
'
|
||||||
|
|
||||||
# Create first-boot.sh
|
# Create first-boot.sh + disable cloud-init (in same block we know works)
|
||||||
- |
|
- |
|
||||||
curtin in-target --target=/target -- bash -c '
|
curtin in-target --target=/target -- bash -c '
|
||||||
|
mkdir -p /etc/cloud/cloud.cfg.d
|
||||||
|
echo "datasource_list: [None]" > /etc/cloud/cloud.cfg.d/99-nocloud.cfg
|
||||||
|
touch /etc/cloud/cloud-init.disabled
|
||||||
|
ln -sf /dev/null /etc/systemd/system/systemd-networkd-wait-online.service
|
||||||
cat <<"EOF" > /opt/first-boot.sh
|
cat <<"EOF" > /opt/first-boot.sh
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
CIDATA_DEV=$(blkid -L CIDATA)
|
CIDATA_DEV=$(blkid -L CIDATA)
|
||||||
@@ -102,13 +116,12 @@ autoinstall:
|
|||||||
'
|
'
|
||||||
- curtin in-target --target=/target -- chmod +x /etc/rc.local
|
- curtin in-target --target=/target -- chmod +x /etc/rc.local
|
||||||
|
|
||||||
# Disable cloud-init on the installed system (no longer needed after autoinstall)
|
|
||||||
- curtin in-target --target=/target -- touch /etc/cloud/cloud-init.disabled
|
|
||||||
- curtin in-target --target=/target -- dpkg --configure -a
|
|
||||||
- curtin in-target --target=/target -- apt-get remove -y cloud-init cloud-guest-utils
|
|
||||||
|
|
||||||
user-data:
|
user-data:
|
||||||
disable_root: false
|
disable_root: false
|
||||||
|
runcmd:
|
||||||
|
- touch /etc/cloud/cloud-init.disabled
|
||||||
|
- systemctl disable cloud-init.service cloud-init-local.service cloud-config.service cloud-final.service
|
||||||
|
- systemctl mask cloud-init.service cloud-init-local.service cloud-config.service cloud-final.service
|
||||||
|
|
||||||
refresh-installer:
|
refresh-installer:
|
||||||
update: no
|
update: no
|
||||||
|
|||||||
55
build-usb.sh
55
build-usb.sh
@@ -103,25 +103,50 @@ for part in "${USB_DEV}"*; do
|
|||||||
umount "$part" 2>/dev/null || true
|
umount "$part" 2>/dev/null || true
|
||||||
done
|
done
|
||||||
|
|
||||||
# --- Write ISO to USB ---
|
# --- Rebuild ISO with 'autoinstall' kernel parameter ---
|
||||||
echo "[2/6] Writing Ubuntu ISO to $USB_DEV (this may take several minutes)..."
|
echo "[2/6] Rebuilding ISO with autoinstall kernel parameter..."
|
||||||
|
|
||||||
# Patch ISO to add 'autoinstall' kernel parameter (skips confirmation prompt)
|
ISO_WORK=$(mktemp -d)
|
||||||
PATCHED_ISO=$(mktemp /tmp/ubuntu-autoinstall-XXXXXX.iso)
|
7z -y x "$ISO_PATH" -o"$ISO_WORK/iso" >/dev/null 2>&1
|
||||||
cp "$ISO_PATH" "$PATCHED_ISO"
|
mv "$ISO_WORK/iso/[BOOT]" "$ISO_WORK/BOOT"
|
||||||
PATCHED_GRUB=$(mktemp /tmp/grub-XXXXXX.cfg)
|
chmod -R u+w "$ISO_WORK/iso"
|
||||||
xorriso -osirrox on -indev "$ISO_PATH" -extract /boot/grub/grub.cfg "$PATCHED_GRUB" 2>/dev/null
|
|
||||||
sed -i 's|linux\t/casper/vmlinuz ---|linux\t/casper/vmlinuz autoinstall ---|' "$PATCHED_GRUB"
|
|
||||||
sed -i 's/^set timeout=30/set timeout=5/' "$PATCHED_GRUB"
|
|
||||||
xorriso -indev "$PATCHED_ISO" -outdev "$PATCHED_ISO" \
|
|
||||||
-map "$PATCHED_GRUB" /boot/grub/grub.cfg \
|
|
||||||
-boot_image any replay 2>/dev/null
|
|
||||||
echo " Patched GRUB: added 'autoinstall' kernel param, reduced timeout to 5s"
|
|
||||||
|
|
||||||
ISO_SIZE=$(stat -c%s "$PATCHED_ISO")
|
# Patch grub.cfg: add 'autoinstall' to kernel cmdline, reduce timeout
|
||||||
|
sed -i 's|linux\t/casper/vmlinuz ---|linux\t/casper/vmlinuz autoinstall ---|' "$ISO_WORK/iso/boot/grub/grub.cfg"
|
||||||
|
sed -i 's/^set timeout=30/set timeout=5/' "$ISO_WORK/iso/boot/grub/grub.cfg"
|
||||||
|
|
||||||
|
PATCHED_ISO="$ISO_WORK/patched.iso"
|
||||||
|
cd "$ISO_WORK/iso"
|
||||||
|
xorriso -as mkisofs -r \
|
||||||
|
-V 'Ubuntu-Server 24.04.3 LTS amd64' \
|
||||||
|
-o "$PATCHED_ISO" \
|
||||||
|
--grub2-mbr ../BOOT/1-Boot-NoEmul.img \
|
||||||
|
--protective-msdos-label \
|
||||||
|
-partition_cyl_align off \
|
||||||
|
-partition_offset 16 \
|
||||||
|
--mbr-force-bootable \
|
||||||
|
-append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b ../BOOT/2-Boot-NoEmul.img \
|
||||||
|
-appended_part_as_gpt \
|
||||||
|
-iso_mbr_part_type a2a0d0ebe5b9334487c068b6b72699c7 \
|
||||||
|
-c '/boot.catalog' \
|
||||||
|
-b '/boot/grub/i386-pc/eltorito.img' \
|
||||||
|
-no-emul-boot \
|
||||||
|
-boot-load-size 4 \
|
||||||
|
-boot-info-table \
|
||||||
|
--grub2-boot-info \
|
||||||
|
-eltorito-alt-boot \
|
||||||
|
-e '--interval:appended_partition_2:::' \
|
||||||
|
-no-emul-boot \
|
||||||
|
-boot-load-size 10160 \
|
||||||
|
. 2>/dev/null
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
echo " ISO rebuilt with 'autoinstall' kernel param and 5s GRUB timeout"
|
||||||
|
|
||||||
|
echo " Writing patched ISO to $USB_DEV..."
|
||||||
dd if="$PATCHED_ISO" of="$USB_DEV" bs=4M status=progress oflag=sync
|
dd if="$PATCHED_ISO" of="$USB_DEV" bs=4M status=progress oflag=sync
|
||||||
sync
|
sync
|
||||||
rm -f "$PATCHED_ISO" "$PATCHED_GRUB"
|
ISO_SIZE=$(stat -c%s "$PATCHED_ISO")
|
||||||
|
rm -rf "$ISO_WORK"
|
||||||
|
|
||||||
# --- Find the end of the ISO to create CIDATA partition ---
|
# --- Find the end of the ISO to create CIDATA partition ---
|
||||||
echo "[3/6] Creating CIDATA partition after ISO data..."
|
echo "[3/6] Creating CIDATA partition after ISO data..."
|
||||||
|
|||||||
Reference in New Issue
Block a user