From acdcb6550a2e269325eb9927408be6d816f14e0b Mon Sep 17 00:00:00 2001 From: Guy Sheffer Date: Tue, 8 Sep 2026 12:02:15 +0300 Subject: [PATCH] fix: detach systemd-firstboot stdio from console for headless boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Raspberry Pi 5 (Debian trixie, kernel 6.12.47) the firstboot wizard child blocks opening /dev/console: sysinit.target stalls, SSH/LightDM never start, and every console writer blocks — the boot appears frozen (reproduced on hardware; the same image completes first boot under QEMU). Verified fix on Pi 5 hardware: ship a drop-in detaching the unit's stdio from the console. Prompts then read EOF and the wizard exits immediately (exit 0, verified offline), while the unit still runs — machine-id per-install regeneration, credential import and first-boot-complete.target are all preserved (no masking). BASE_FIRSTBOOT_NONINTERACTIVE=no restores console stdio for distros that ship a display/keyboard wizard. Evidence: hang reproduced with the pristine wizard (forked child, no SIGCHLD, 16min), fixed boot reaches graphical.target with the drop-in. --- src/modules/base/config | 6 ++++++ src/modules/base/end_chroot_script | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/modules/base/config b/src/modules/base/config index 600c04e9..2fb7f629 100644 --- a/src/modules/base/config +++ b/src/modules/base/config @@ -111,6 +111,12 @@ fi #Keyboard [ -n "$BASE_CONFIG_KEYBOARD" ] || BASE_CONFIG_KEYBOARD=default +# Guarantee headless first boot: seed every systemd-firstboot prompt +# (locale, keymap, timezone, root password credential) at build time so +# the wizard never blocks sysinit.target waiting for console input. +# Set to "no" to keep the interactive first-boot wizard. +[ -n "$BASE_FIRSTBOOT_NONINTERACTIVE" ] || BASE_FIRSTBOOT_NONINTERACTIVE=yes + # Arch for now either armv7l, arm64 or aarch64 [ -n "$BASE_ARCH" ] || BASE_ARCH=armv7l diff --git a/src/modules/base/end_chroot_script b/src/modules/base/end_chroot_script index 0a7a9e82..f5f1ee81 100755 --- a/src/modules/base/end_chroot_script +++ b/src/modules/base/end_chroot_script @@ -34,6 +34,24 @@ fi echo "$BASE_OVERRIDE_HOSTNAME" > /etc/hostname sed -i -e "s@${FILE_HOST_NAME}@$BASE_OVERRIDE_HOSTNAME@g" /etc/hosts +# Headless first boot: systemd-firstboot.service runs its wizard with +# StandardOutput/Error=tty and prompts on /dev/console. On Raspberry Pi 5 +# (kernel 6.12.47) the wizard child opening /dev/console deadlocks the boot: +# sysinit.target stalls (SSH/LightDM never start) and every console writer +# blocks — the whole boot looks frozen. Reproduced on hardware; the same image +# completes first boot in QEMU. Verified fix: run the wizard with stdio +# detached from the console. Prompts then read EOF and the wizard exits +# immediately (verified: exit 0), the unit still runs (machine-id handling, +# credentials, first-boot-complete.target all preserved — nothing masked). +# Set BASE_FIRSTBOOT_NONINTERACTIVE=no to keep console stdio for distros +# that attach a display/keyboard. +if [ "${BASE_FIRSTBOOT_NONINTERACTIVE}" != "no" ]; then + echo "firstboot: detaching systemd-firstboot stdio from console (headless fix)" + mkdir -p /etc/systemd/system/systemd-firstboot.service.d + printf '[Service]\nStandardInput=null\nStandardOutput=null\nStandardError=null\n' \ + > /etc/systemd/system/systemd-firstboot.service.d/headless.conf +fi + if [ "${BASE_DISTRO}" == "ubuntu" ];then echo "127.0.0.1 ${BASE_OVERRIDE_HOSTNAME}" > /etc/hosts fi