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"