From ccb5d29b1cc2da2a38cfbc0622094a9b628acce3 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Sun, 31 May 2026 07:43:55 +0200 Subject: [PATCH] fix(rpi-usb): kiosk install fail-loud + pre-rsync assertion (closes #433) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three changes to Step 5.4 of image/build-rpi-usb.sh: 1. **apt --fix-broken install FIRST** — the secubox-* .debs installed via dpkg -i in Step 5 (no dep resolution) leave the rootfs with broken deps (lxc, debootstrap, python3-cryptography, certbot, netdata, ... all unmet). apt refuses any new install while that state exists, so chromium/xserver-xorg/openbox installs silently failed. fix-broken clears the state (~500 MB extra) BEFORE the kiosk install. This is the root cause of #433. 2. **Fail-loud on every step** — was `chroot apt-get ... 2>/dev/null || warn "Some kiosk packages may have failed (continuing)"`. The `|| warn` swallowed apt failures and the script printed `[OK] Kiosk mode installed and enabled` even when nothing was actually installed. Now apt errors abort the build (err exits non-zero). Silently shipping a no-kiosk image is worse than no image — if --kiosk is passed, the user expects kiosk. 3. **Build-time assertion before Step 7 (rsync)** — verifies that EVERY kiosk artefact made it into ${ROOTFS}: - chromium / startx / openbox binaries - secubox-kiosk.sh launcher + .xinitrc - /etc/systemd/system/secubox-kiosk.service file - /var/lib/secubox/boot-mode == "kiosk" - default.target → graphical.target symlink - secubox-kiosk.service enabled (graphical.target.wants symlink) Any missing artefact aborts the build. No more discovering after flash that the .img has no kiosk despite a green CI run. Also drops the `2>/dev/null` masking on systemctl set-default and enable — these now fail loud too (and shouldn't fail anymore since the X stack is properly installed at that point). Observed v2.13.4: image v2.13.4 shipped with boot-mode="normal", no chromium, no secubox-kiosk.service, default.target=multi-user. The CI log claimed "[OK] Kiosk mode installed and enabled". The apt step had failed loud with "apt --fix-broken install to correct these" but the warn swallowed it. Expected v2.13.5: rpi400 image properly ships kiosk-by-default, OR the CI fails clearly with "kiosk artefacts incomplete — refusing to publish a broken image" if any prerequisite is missing. --- image/build-rpi-usb.sh | 77 +++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/image/build-rpi-usb.sh b/image/build-rpi-usb.sh index ca8c8b6e..231314a4 100755 --- a/image/build-rpi-usb.sh +++ b/image/build-rpi-usb.sh @@ -787,21 +787,36 @@ ok "SecuBox packages installed" # boot-mode file to "kiosk" so first boot lands directly in the kiosk. if [[ "${INCLUDE_KIOSK}" -eq 1 ]]; then log "Installing kiosk mode (chromium fullscreen → http://127.0.0.1/) ..." - chroot "${ROOTFS}" apt-get install -y -q --no-install-recommends \ - xserver-xorg xinit openbox chromium x11-xserver-utils ca-certificates \ - 2>/dev/null || warn "Some kiosk packages may have failed (continuing)" + + # The secubox-* .debs installed via dpkg -i in Step 5 (no dep resolution) + # leave the rootfs in a broken-deps state. apt refuses any new install + # while that state exists, so --fix-broken must run FIRST. This pulls in + # lxc / debootstrap / python3-cryptography / netdata / certbot / ... + # (~500 MB extra). Required for #433 — without it the chromium install + # below silently fails with "Some packages were not installed". + log " apt --fix-broken install (clear pre-existing broken-deps state)" + chroot "${ROOTFS}" /bin/bash -c \ + 'DEBIAN_FRONTEND=noninteractive apt-get --fix-broken install -y -q' \ + || err "apt --fix-broken install failed inside chroot — kiosk install aborted" + + # Fail-loud on apt errors (was silently masked with || warn, #433 root cause). + # If chromium/X can't install, abort the whole image build — silently + # shipping a no-kiosk image is worse than no image. + log " apt-get install kiosk stack" + chroot "${ROOTFS}" /bin/bash -c \ + 'DEBIAN_FRONTEND=noninteractive apt-get install -y -q --no-install-recommends \ + xserver-xorg xinit openbox chromium x11-xserver-utils \ + ca-certificates dbus-x11' \ + || err "apt-get install failed inside chroot — kiosk packages required when --kiosk is passed" KIOSK_SRC="${SCRIPT_DIR}/kiosk" - if [[ -d "${KIOSK_SRC}" ]]; then - install -d "${ROOTFS}/usr/share/secubox/kiosk" - install -m 0755 "${KIOSK_SRC}/secubox-kiosk.sh" \ - "${ROOTFS}/usr/share/secubox/kiosk/secubox-kiosk.sh" - install -m 0755 "${KIOSK_SRC}/xinitrc" \ - "${ROOTFS}/root/.xinitrc" - ok "Copied kiosk launcher + xinitrc from ${KIOSK_SRC}" - else - warn "image/kiosk/ source missing — kiosk scripts not installed" - fi + [[ -d "${KIOSK_SRC}" ]] || err "image/kiosk/ source missing — required for --kiosk" + install -d "${ROOTFS}/usr/share/secubox/kiosk" + install -m 0755 "${KIOSK_SRC}/secubox-kiosk.sh" \ + "${ROOTFS}/usr/share/secubox/kiosk/secubox-kiosk.sh" + install -m 0755 "${KIOSK_SRC}/xinitrc" \ + "${ROOTFS}/root/.xinitrc" + ok "Copied kiosk launcher + xinitrc from ${KIOSK_SRC}" # secubox-kiosk.service: matches the unit name apply_mode already # enables/disables (lines ~353/357 of this script). Runs startx on vt7 @@ -835,9 +850,39 @@ KIOSKSVC install -d "${ROOTFS}/var/lib/secubox" echo "kiosk" > "${ROOTFS}/var/lib/secubox/boot-mode" - chroot "${ROOTFS}" systemctl set-default graphical.target 2>/dev/null || true - chroot "${ROOTFS}" systemctl enable secubox-kiosk.service 2>/dev/null || true - ok "Kiosk mode installed and enabled (default boot mode = kiosk)" + # Fail-loud — graphical.target must exist now that xserver-xorg is installed. + chroot "${ROOTFS}" systemctl set-default graphical.target \ + || err "systemctl set-default graphical.target failed — X stack not installed?" + chroot "${ROOTFS}" systemctl enable secubox-kiosk.service \ + || err "systemctl enable secubox-kiosk.service failed" + + # Build-time assertion (#433): verify EVERY kiosk artefact made it into + # the rootfs before Step 7's rsync. If any of these is missing, the .img + # would ship without kiosk despite the CI logging "Kiosk mode installed". + log " Asserting kiosk artefacts in rootfs (closes #433 silent-fail bug)" + _kiosk_fail=0 + for _f in \ + "${ROOTFS}/usr/bin/chromium" \ + "${ROOTFS}/usr/bin/startx" \ + "${ROOTFS}/usr/bin/openbox" \ + "${ROOTFS}/usr/share/secubox/kiosk/secubox-kiosk.sh" \ + "${ROOTFS}/root/.xinitrc" \ + "${ROOTFS}/etc/systemd/system/secubox-kiosk.service" \ + "${ROOTFS}/var/lib/secubox/boot-mode" \ + ; do + [[ -e "${_f}" ]] || { warn "MISSING: ${_f}"; _kiosk_fail=1; } + done + [[ "$(cat "${ROOTFS}/var/lib/secubox/boot-mode" 2>/dev/null)" == "kiosk" ]] \ + || { warn "boot-mode != 'kiosk'"; _kiosk_fail=1; } + [[ "$(readlink "${ROOTFS}/etc/systemd/system/default.target" 2>/dev/null)" \ + == *"graphical.target" ]] || { warn "default.target != graphical.target"; _kiosk_fail=1; } + [[ -e "${ROOTFS}/etc/systemd/system/graphical.target.wants/secubox-kiosk.service" ]] \ + || { warn "secubox-kiosk.service not in graphical.target.wants/"; _kiosk_fail=1; } + + [[ "${_kiosk_fail}" -eq 0 ]] \ + || err "Kiosk artefacts incomplete — refusing to publish a broken image" + + ok "Kiosk mode installed and enabled (default boot mode = kiosk, all artefacts verified)" else log "Kiosk mode skipped (pass --kiosk to enable; #423)" fi