From 3676157a7ce1914833441ac349158370aa96126b Mon Sep 17 00:00:00 2001 From: "CanbiZ (MickLesk)" <47820557+MickLesk@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:26:20 +0100 Subject: [PATCH] Debian13-VM: Optimize First Boot & add noCloud/Cloud Selection (#11810) * fix(debian-13-vm): disable systemd-firstboot and add autologin via virt-customize Newer Debian 13 (Trixie) nocloud images (Jan 29+) have systemd-firstboot enabled, which blocks the boot process by prompting for timezone and root password on the serial console. The noVNC console stalls after auditd checks. Fix by using virt-customize (like docker-vm.sh) to: - Disable systemd-firstboot.service and mask it - Pre-seed timezone to Etc/UTC - Configure autologin on ttyS0 and tty1 for nocloud images - Set hostname and clear machine-id for unique IDs - Install libguestfs-tools if not present Fixes #11807 * feat(debian-13-vm): add cloud-init selection dialog for default and advanced settings Add select_cloud_init() function consistent with docker-vm.sh that prompts the user to choose between Cloud-Init (genericcloud image) and nocloud (with auto-login) in both default and advanced settings. Previously, default settings hardcoded CLOUD_INIT=no without asking. --- vm/debian-13-vm.sh | 83 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/vm/debian-13-vm.sh b/vm/debian-13-vm.sh index 6082e89a1..af036768e 100644 --- a/vm/debian-13-vm.sh +++ b/vm/debian-13-vm.sh @@ -201,6 +201,17 @@ function exit-script() { exit } +function select_cloud_init() { + if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" \ + --yesno "Enable Cloud-Init for VM configuration?\n\nCloud-Init allows automatic configuration of:\n- User accounts and passwords\n- SSH keys\n- Network settings (DHCP/Static)\n- DNS configuration\n\nYou can also configure these settings later in Proxmox UI.\n\nNote: Without Cloud-Init, the nocloud image will be used with console auto-login." --defaultno 18 68); then + CLOUD_INIT="yes" + echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}yes${CL}" + else + CLOUD_INIT="no" + echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}no${CL}" + fi +} + function default_settings() { VMID=$(get_valid_nextid) FORMAT=",efitype=4m" @@ -216,7 +227,6 @@ function default_settings() { VLAN="" MTU="" START_VM="yes" - CLOUD_INIT="no" METHOD="default" echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}" echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}" @@ -230,7 +240,7 @@ function default_settings() { echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}" echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}" echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}" - echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}no${CL}" + select_cloud_init echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}" echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 13 VM using the above default settings${CL}" } @@ -400,13 +410,7 @@ function advanced_settings() { exit-script fi - if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" --yesno "Configure the VM with Cloud-init?" --defaultno 10 58); then - echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}yes${CL}" - CLOUD_INIT="yes" - else - echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}no${CL}" - CLOUD_INIT="no" - fi + select_cloud_init if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}" @@ -473,6 +477,17 @@ else fi msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location." msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}." + +# ============================================================================== +# PREREQUISITES +# ============================================================================== +if ! command -v virt-customize &>/dev/null; then + msg_info "Installing libguestfs-tools" + apt-get update >/dev/null 2>&1 + apt-get install -y libguestfs-tools >/dev/null 2>&1 + msg_ok "Installed libguestfs-tools" +fi + msg_info "Retrieving the URL for the Debian 13 Qcow2 Disk Image" if [ "$CLOUD_INIT" == "yes" ]; then URL=https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2 @@ -486,6 +501,50 @@ echo -en "\e[1A\e[0K" FILE=$(basename $URL) msg_ok "Downloaded ${CL}${BL}${FILE}${CL}" +# ============================================================================== +# IMAGE CUSTOMIZATION +# ============================================================================== +msg_info "Customizing ${FILE} image" + +WORK_FILE=$(mktemp --suffix=.qcow2) +cp "$FILE" "$WORK_FILE" + +# Set hostname +virt-customize -q -a "$WORK_FILE" --hostname "${HN}" >/dev/null 2>&1 + +# Prepare for unique machine-id on first boot +virt-customize -q -a "$WORK_FILE" --run-command "truncate -s 0 /etc/machine-id" >/dev/null 2>&1 +virt-customize -q -a "$WORK_FILE" --run-command "rm -f /var/lib/dbus/machine-id" >/dev/null 2>&1 + +# Disable systemd-firstboot to prevent interactive prompts blocking the console +virt-customize -q -a "$WORK_FILE" --run-command "systemctl disable systemd-firstboot.service 2>/dev/null; rm -f /etc/systemd/system/sysinit.target.wants/systemd-firstboot.service; ln -sf /dev/null /etc/systemd/system/systemd-firstboot.service" >/dev/null 2>&1 || true + +# Pre-seed firstboot settings so it won't prompt even if triggered +virt-customize -q -a "$WORK_FILE" --run-command "echo 'Etc/UTC' > /etc/timezone && ln -sf /usr/share/zoneinfo/Etc/UTC /etc/localtime" >/dev/null 2>&1 || true +virt-customize -q -a "$WORK_FILE" --run-command "touch /etc/locale.conf" >/dev/null 2>&1 || true + +if [ "$CLOUD_INIT" == "yes" ]; then + # Cloud-Init handles SSH and login + virt-customize -q -a "$WORK_FILE" --run-command "sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config" >/dev/null 2>&1 || true + virt-customize -q -a "$WORK_FILE" --run-command "sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config" >/dev/null 2>&1 || true +else + # Configure auto-login on serial console (ttyS0) and virtual console (tty1) + virt-customize -q -a "$WORK_FILE" --run-command "mkdir -p /etc/systemd/system/serial-getty@ttyS0.service.d" >/dev/null 2>&1 || true + virt-customize -q -a "$WORK_FILE" --run-command 'cat > /etc/systemd/system/serial-getty@ttyS0.service.d/autologin.conf << EOF +[Service] +ExecStart= +ExecStart=-/sbin/agetty --autologin root --noclear %I \$TERM +EOF' >/dev/null 2>&1 || true + virt-customize -q -a "$WORK_FILE" --run-command "mkdir -p /etc/systemd/system/getty@tty1.service.d" >/dev/null 2>&1 || true + virt-customize -q -a "$WORK_FILE" --run-command 'cat > /etc/systemd/system/getty@tty1.service.d/autologin.conf << EOF +[Service] +ExecStart= +ExecStart=-/sbin/agetty --autologin root --noclear %I \$TERM +EOF' >/dev/null 2>&1 || true +fi + +msg_ok "Customized image" + STORAGE_TYPE=$(pvesm status -storage "$STORAGE" | awk 'NR>1 {print $2}') case $STORAGE_TYPE in nfs | dir) @@ -512,7 +571,7 @@ msg_info "Creating a Debian 13 VM" qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \ -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null -qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null +qm importdisk $VMID ${WORK_FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null if [ "$CLOUD_INIT" == "yes" ]; then qm set $VMID \ -efidisk0 ${DISK0_REF}${FORMAT} \ @@ -527,6 +586,10 @@ else -boot order=scsi0 \ -serial0 socket >/dev/null fi + +# Clean up work file +rm -f "$WORK_FILE" + DESCRIPTION=$( cat <