From f644a80c9adf7ed6c2bbdcc5200e97f6a0657eb0 Mon Sep 17 00:00:00 2001 From: lrnselfreliance <33263708+lrnselfreliance@users.noreply.github.com> Date: Wed, 14 Oct 2026 18:23:40 -0600 Subject: [PATCH] Debian installs create the user the installer asks for (#834) The ISO's chroot hook created wrolpi as a login user (UID 1000, password "wrolpi", full sudo, LightDM autologin). The Debian installer creates the user it asks for only when no UID 1000-59999 user exists, so it silently skipped that user: the only login on an installed system was wrolpi/wrolpi, with SSH and sudo. wrolpi is now a system account with no password or login sudo, as on every other WROLPi deployment. The installer creates the user it asks for (with sudo, no autologin). The live session logs in as live-config's "user". Desktop shortcuts moved to /etc/skel so every user gets them. check-iso.sh now fails the build when the image has a UID 1000-59999 user. Co-authored-by: Claude Opus 5.5 --- debian-live-config/README.md | 15 ++++-- debian-live-config/build.sh | 2 +- debian-live-config/check-iso.sh | 31 +++++++++-- .../hooks/normal/9999-wrolpi.hook.chroot | 52 +++++++------------ .../usr/local/bin/wrolpi-firstboot-notify | 4 +- 5 files changed, 61 insertions(+), 43 deletions(-) diff --git a/debian-live-config/README.md b/debian-live-config/README.md index 0ec29aee..d728274b 100644 --- a/debian-live-config/README.md +++ b/debian-live-config/README.md @@ -17,8 +17,9 @@ sudo ./build.sh # build from 'release' branch sudo ./build.sh -b master # build from a specific branch ``` -Requires Debian / Ubuntu with `live-build` and `libarchive-tools` (bsdtar) -installed. The resulting ISO is written to this directory as +Requires Debian / Ubuntu with `live-build`, `libarchive-tools` (bsdtar), +`genisoimage` (isoinfo) and `squashfs-tools` installed. The resulting ISO is +written to this directory as `WROLPi-v${VERSION}-amd64.iso`, and `check-iso.sh` then checks it for problems that would only appear after the Debian installer runs. @@ -60,6 +61,14 @@ is no safe, filesystem-agnostic way to graft WROLPi onto a full drive. Afterwards, future ISO upgrades preserve your library via the `upgrade` command above. +## Users + +- `wrolpi` is a system account (no password, no login sudo) that owns + `/media/wrolpi` and runs the WROLPi services, as on every other WROLPi. +- The live session logs in automatically as `user` (live-config). +- An installed system has the user the Debian installer asked for, with sudo, + and no automatic login. + ## Layout on disk The drive carries everything WROLPi needs. The SQLite database lives @@ -117,7 +126,7 @@ needing a dedicated drive.) - [x] **Phase 1 — merged live + chroot config**: Single `debian-live-config/` produces a Debian Live ISO with the full WROLPi stack, XFCE auto-login - as `wrolpi`, persistence partition created on first boot. + as `user`, persistence partition created on first boot. - [x] **Phase 2 — Debian Installer**: Standard `debian-installer` bundled via `lb config --debian-installer live --debian-installer-gui true`. GRUB exposes "Live", "Install", and "Graphical Install" entries. diff --git a/debian-live-config/build.sh b/debian-live-config/build.sh index a08b744a..0b5d7d1c 100755 --- a/debian-live-config/build.sh +++ b/debian-live-config/build.sh @@ -96,7 +96,7 @@ lb config \ --color \ --linux-packages "linux-image linux-headers" \ --memtest memtest86+ \ - --bootappend-live "boot=live components quiet splash noswap persistence persistence-storage=filesystem persistence-media=removable persistence-label=persistence live-config.username=wrolpi live-config.user-fullname=WROLPi live-config.hostname=wrolpi" \ + --bootappend-live "boot=live components quiet splash noswap persistence persistence-storage=filesystem persistence-media=removable persistence-label=persistence live-config.username=user live-config.user-fullname=WROLPi live-config.hostname=wrolpi" \ --iso-volume "WROLPi v${VERSION}" \ --iso-application "WROLPi v${VERSION}" \ --iso-preparer WROLPi \ diff --git a/debian-live-config/check-iso.sh b/debian-live-config/check-iso.sh index 2fb184f5..4f6de54d 100755 --- a/debian-live-config/check-iso.sh +++ b/debian-live-config/check-iso.sh @@ -5,7 +5,8 @@ # # ./check-iso.sh WROLPi-v0.30.0-beta-amd64.iso # -# Requires bsdtar (Debian package libarchive-tools; built into macOS). +# Requires bsdtar (libarchive-tools), isoinfo (genisoimage) and unsquashfs +# (squashfs-tools). ISO=$1 if [ -z "${ISO}" ] || [ ! -f "${ISO}" ]; then @@ -13,10 +14,12 @@ if [ -z "${ISO}" ] || [ ! -f "${ISO}" ]; then exit 1 fi -if ! command -v bsdtar >/dev/null 2>&1; then - echo "ERROR: bsdtar is required (apt install libarchive-tools)." >&2 - exit 1 -fi +for tool in bsdtar:libarchive-tools isoinfo:genisoimage unsquashfs:squashfs-tools; do + if ! command -v "${tool%%:*}" >/dev/null 2>&1; then + echo "ERROR: ${tool%%:*} is required (apt install ${tool#*:})." >&2 + exit 1 + fi +done TMP=$(mktemp -d) trap 'rm -rf "${TMP}"' EXIT @@ -48,6 +51,24 @@ if extract live/filesystem.packages-remove && [ -s "${TMP}/filesystem.packages-r FAILED=1 fi +# The Debian installer creates the user it asks for only if no user with a UID +# from 1000 to 59999 exists (user-setup's is_system_user); otherwise it skips +# that user silently. wrolpi must be a system account (UID < 1000), as on +# every other WROLPi deployment. +SQUASHFS_LBA=$(isoinfo -i "${ISO}" -R -l 2>/dev/null \ + | awk '/ filesystem\.squashfs/ {sub(/.*\[ */, ""); print $1; exit}') +if [ -z "${SQUASHFS_LBA}" ] \ + || ! unsquashfs -o $((SQUASHFS_LBA * 2048)) -cat "${ISO}" etc/passwd > "${TMP}/passwd" 2>/dev/null; then + echo "ERROR: could not read /etc/passwd from live/filesystem.squashfs in ${ISO}." >&2 + exit 1 +fi +if awk -F: '$3 >= 1000 && $3 < 60000 {found=1} END {exit !found}' "${TMP}/passwd"; then + echo "ERROR: the Debian installer would not create the user it asks for, because these users exist:" >&2 + awk -F: '$3 >= 1000 && $3 < 60000 {print " " $1 " (UID " $3 ")"}' "${TMP}/passwd" >&2 + echo "Create them with useradd --system." >&2 + FAILED=1 +fi + if [ "${FAILED}" -ne 0 ]; then exit 1 fi diff --git a/debian-live-config/config/hooks/normal/9999-wrolpi.hook.chroot b/debian-live-config/config/hooks/normal/9999-wrolpi.hook.chroot index 1882a5c5..9b86a2ef 100644 --- a/debian-live-config/config/hooks/normal/9999-wrolpi.hook.chroot +++ b/debian-live-config/config/hooks/normal/9999-wrolpi.hook.chroot @@ -21,14 +21,14 @@ alias ll='ls -lh' alias la='ll -a' EOF -# Pre-create the wrolpi user. Same account is used for interactive desktop -# login (password 'wrolpi') AND as the User= for the wrolpi-* systemd -# services. live-config sees this existing user at boot and skips its own -# user creation (preserving our chosen password); the boot params set -# live-config.username=wrolpi so live-config's other scripts (sudo, -# lightdm autologin) target this account. -useradd -m -s /bin/bash -U -G sudo,audio,video,cdrom,plugdev,netdev wrolpi -echo "wrolpi:wrolpi" | chpasswd +# The wrolpi service account owns /media/wrolpi and runs the wrolpi-* +# services, as on every other WROLPi deployment. It has no password and no +# login sudo; 90-wrolpi grants it specific commands only. It must be a +# system account (UID < 1000): the Debian installer creates the user it asks +# for only when no UID 1000-59999 user exists (see check-iso.sh). People log +# in as that installer user; the live session's "user" comes from live-config +# (live-config.username in build.sh), which also sets up its autologin. +useradd --system -m -d /home/wrolpi -s /bin/bash -U wrolpi # Rebrand from generic Debian so users don't think they have the wrong USB. echo "wrolpi" > /etc/hostname @@ -189,31 +189,19 @@ banner-message-enable=true banner-message-text=WROLPi EOF -# LightDM auto-login — drop straight into the XFCE session as wrolpi without -# a password prompt. The wrolpi password ('wrolpi') is still required for -# sudo and screen unlock. -mkdir -p /etc/lightdm/lightdm.conf.d -cat > /etc/lightdm/lightdm.conf.d/50-wrolpi-autologin.conf <<'EOF' -[Seat:*] -autologin-user=wrolpi -autologin-user-timeout=0 -autologin-session=xfce -EOF +# Desktop shortcuts to WROLPi's services, in /etc/skel so every login user +# gets them: the live session's "user" and the user the installer creates. +# Use the canonical .desktop files from the repo (etc/raspberrypios/) so +# updates to those files propagate to the live ISO without touching the +# chroot hook. wrolpi-trust-desktop-icons.desktop autostart marks each as +# trusted at session start so XFCE will launch them on double-click. +mkdir -p /etc/skel/Desktop +cp /opt/wrolpi/etc/raspberrypios/wrolpi.desktop /etc/skel/Desktop/ +cp /opt/wrolpi/etc/raspberrypios/controller.desktop /etc/skel/Desktop/ +cp /opt/wrolpi/etc/raspberrypios/wrolpi-help.desktop /etc/skel/Desktop/ +cp /opt/wrolpi/etc/raspberrypios/wrolpi-help-files.desktop /etc/skel/Desktop/ -mkdir -p /home/wrolpi/Desktop - -# Desktop shortcuts to WROLPi's services. Use the canonical .desktop -# files from the repo (etc/raspberrypios/) so updates to those files -# propagate to the live ISO without touching the chroot hook. -# wrolpi-trust-desktop-icons.desktop autostart marks each as trusted at -# session start so XFCE will launch them on double-click. -cp /opt/wrolpi/etc/raspberrypios/wrolpi.desktop /home/wrolpi/Desktop/ -cp /opt/wrolpi/etc/raspberrypios/controller.desktop /home/wrolpi/Desktop/ -cp /opt/wrolpi/etc/raspberrypios/wrolpi-help.desktop /home/wrolpi/Desktop/ -cp /opt/wrolpi/etc/raspberrypios/wrolpi-help-files.desktop /home/wrolpi/Desktop/ - -chmod +x /home/wrolpi/Desktop/*.desktop -chown -R wrolpi:wrolpi /home/wrolpi/Desktop +chmod +x /etc/skel/Desktop/*.desktop # Protect blob files from accidental modification or deletion. if [ -d /opt/wrolpi-blobs ] && ls /opt/wrolpi-blobs/* >/dev/null 2>&1; then diff --git a/debian-live-config/config/includes.chroot/usr/local/bin/wrolpi-firstboot-notify b/debian-live-config/config/includes.chroot/usr/local/bin/wrolpi-firstboot-notify index 35aa747d..f2ca3244 100755 --- a/debian-live-config/config/includes.chroot/usr/local/bin/wrolpi-firstboot-notify +++ b/debian-live-config/config/includes.chroot/usr/local/bin/wrolpi-firstboot-notify @@ -37,8 +37,8 @@ elif command -v notify-send >/dev/null 2>&1; then fi # bootstrap.sh writes the summary as root; /tmp's sticky bit means a -# non-root rm fails. Try via sudo (passwordless on WROLPi) so the file -# doesn't survive into another login session. +# non-root rm fails. Try via sudo (passwordless for the live session's +# user) so the file doesn't survive into another login session. sudo rm -f "$F" 2>/dev/null || rm -f "$F" 2>/dev/null || true echo "done"