mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
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 <noreply@anthropic.com>
219 lines
9.4 KiB
Bash
219 lines
9.4 KiB
Bash
#!/usr/bin/bash
|
|
# Chroot hook for the combined WROLPi Live + Installer ISO.
|
|
#
|
|
# Composes the full WROLPi stack into the live system during live-build's
|
|
# chroot phase. The resulting squashfs is what runs in live mode AND what
|
|
# the Calamares installer (phase 2) will copy onto the target disk, so any
|
|
# customisation here applies to both deployments.
|
|
|
|
set -e
|
|
set -x
|
|
|
|
# Generate and set default locale to avoid perl warnings.
|
|
# Users can change this later via: sudo dpkg-reconfigure locales
|
|
sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
|
|
locale-gen
|
|
echo 'LANG=en_US.UTF-8' > /etc/default/locale
|
|
export LANG=en_US.UTF-8
|
|
|
|
cat >>/etc/profile <<'EOF'
|
|
alias ll='ls -lh'
|
|
alias la='ll -a'
|
|
EOF
|
|
|
|
# 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
|
|
sed -i 's/127\.0\.1\.1.*/127.0.1.1\twrolpi/' /etc/hosts 2>/dev/null || \
|
|
echo "127.0.1.1 wrolpi" >> /etc/hosts
|
|
cat > /etc/issue <<'EOF'
|
|
WROLPi \n (\l)
|
|
|
|
EOF
|
|
cat > /etc/issue.net <<'EOF'
|
|
WROLPi %h
|
|
|
|
EOF
|
|
|
|
git --version
|
|
|
|
WROLPI_BRANCH="release"
|
|
[ -f /opt/wrolpi-branch ] && WROLPI_BRANCH=$(cat /opt/wrolpi-branch)
|
|
git clone -b "${WROLPI_BRANCH}" https://github.com/lrnselfreliance/wrolpi.git /opt/wrolpi
|
|
rm -f /opt/wrolpi-branch
|
|
|
|
# Install webapp.
|
|
cd /opt/wrolpi/app
|
|
npm --version
|
|
node --version
|
|
npm install
|
|
|
|
# `npm install` rewrites the tracked app/package-lock.json. build_app.sh (below)
|
|
# stamps build/.build-stamp from that working tree, but on-device repair.sh runs
|
|
# `git reset --hard` before it stamps -- reverting the lock -- so a stamp baked
|
|
# against the dirty lock can never match on first boot and the box rebuilds the app.
|
|
# Reset to HEAD here, exactly as repair.sh does, so the baked stamp represents
|
|
# committed source. Only the lock is reverted; build/, node_modules, and the venvs
|
|
# are untracked and survive. HOME is set explicitly so `git config --global`
|
|
# cannot fail (and abort the build under `set -e`) when the chroot leaves HOME
|
|
# unset; safe.directory avoids git's "dubious ownership" refusal.
|
|
export HOME=/root
|
|
git config --global --add safe.directory /opt/wrolpi
|
|
git -C /opt/wrolpi reset --hard HEAD
|
|
|
|
# Build the React production bundle. Without this, /opt/wrolpi/app/build/
|
|
# does not exist and wrolpi-app.service (`serve build -l 3000 ...`) returns
|
|
# 404 for every request. Baking the build into the squashfs means the
|
|
# live image works offline immediately and the installed deployment skips
|
|
# a multi-minute first-boot step. build_app.sh also writes build/.build-stamp
|
|
# so the on-device repair.sh sees this build as current and never rebuilds it.
|
|
/opt/wrolpi/scripts/build_app.sh
|
|
|
|
# Install Node console commands.
|
|
npm i -g serve@12.0.1 single-file-cli@2.0.73 readability-extractor@0.0.6
|
|
|
|
# Install Deno runtime. Hash pinned to detect tampering of the upstream release artifact.
|
|
DENO_VERSION="v2.8.3"
|
|
DENO_SHA256="30455b845ffa6082209c3590269c910ad3b7efdf28c9879afd4006c47ae54197"
|
|
curl -fsSL "https://github.com/denoland/deno/releases/download/${DENO_VERSION}/deno-x86_64-unknown-linux-gnu.zip" -o /tmp/deno.zip
|
|
echo "${DENO_SHA256} /tmp/deno.zip" | sha256sum -c -
|
|
unzip /tmp/deno.zip -d /usr/local/bin/
|
|
chmod +x /usr/local/bin/deno
|
|
rm /tmp/deno.zip
|
|
deno --version
|
|
|
|
# Install Python requirements. Try multiple times because pypi may stop responding.
|
|
python3 --version
|
|
python3 -m venv /opt/wrolpi/venv
|
|
/opt/wrolpi/venv/bin/pip3 install -r /opt/wrolpi/requirements.txt ||
|
|
/opt/wrolpi/venv/bin/pip3 install -r /opt/wrolpi/requirements.txt ||
|
|
/opt/wrolpi/venv/bin/pip3 install -r /opt/wrolpi/requirements.txt
|
|
|
|
# Install Controller with separate venv.
|
|
echo "Pre-installing WROLPi Controller..."
|
|
python3 -m venv /opt/wrolpi/controller/venv
|
|
/opt/wrolpi/controller/venv/bin/pip install --upgrade pip
|
|
/opt/wrolpi/controller/venv/bin/pip install -r /opt/wrolpi/controller/requirements.txt ||
|
|
/opt/wrolpi/controller/venv/bin/pip install -r /opt/wrolpi/controller/requirements.txt ||
|
|
/opt/wrolpi/controller/venv/bin/pip install -r /opt/wrolpi/controller/requirements.txt
|
|
echo "Controller pre-installed"
|
|
|
|
# Configure Caddy. Caddy itself comes from package-lists/ (repository in
|
|
# config/archives/), never apt-get here: the Debian installer purges packages
|
|
# that a hook installs.
|
|
mkdir -p /etc/caddy
|
|
cp /opt/wrolpi/etc/raspberrypios/Caddyfile /etc/caddy/Caddyfile
|
|
mkdir -p /var/www
|
|
cp /opt/wrolpi/etc/raspberrypios/50x.html /var/www/50x.html
|
|
|
|
# WROLPi needs a few privileged commands.
|
|
cp /opt/wrolpi/etc/raspberrypios/90-wrolpi /etc/sudoers.d/90-wrolpi
|
|
chmod 0440 /etc/sudoers.d/90-wrolpi
|
|
# Verify this new file is valid.
|
|
visudo -c -f /etc/sudoers.d/90-wrolpi
|
|
|
|
mkdir /media/wrolpi
|
|
|
|
# Verify blob files were copied in by includes.chroot (downloaded by build.sh).
|
|
[[ -f /opt/wrolpi-blobs/map-fonts.tar.gz && -s /opt/wrolpi-blobs/map-fonts.tar.gz ]] || \
|
|
(echo "ERROR: map-fonts.tar.gz missing from /opt/wrolpi-blobs!" && exit 1)
|
|
[[ -f /opt/wrolpi-blobs/map-overview.pmtiles && -s /opt/wrolpi-blobs/map-overview.pmtiles ]] || \
|
|
(echo "ERROR: map-overview.pmtiles missing from /opt/wrolpi-blobs!" && exit 1)
|
|
|
|
# Ship committed blobs (e.g. the default Zim served by Kiwix when the media dir
|
|
# has no working zims) into /opt/wrolpi-blobs.
|
|
cp /opt/wrolpi/wrolpi/blobs/* /opt/wrolpi-blobs/
|
|
|
|
# Bake in the map toolchain (pmtiles CLI + tippecanoe) so first boot does not
|
|
# need internet. Shared with pi-gen and on-device upgrades via a single script
|
|
# so versions/pins live in one place. It is safe in the chroot: unlike
|
|
# install_protomaps.sh it contains no migration logic that needs a running
|
|
# systemd.
|
|
/opt/wrolpi/wrolpi/scripts/install_map_tools.sh
|
|
|
|
# Install WROLPi Help.
|
|
/opt/wrolpi/scripts/install_help_service.sh
|
|
|
|
cp /opt/wrolpi/etc/raspberrypios/wrolpi-*.service /etc/systemd/system/
|
|
cp /opt/wrolpi/etc/raspberrypios/wrolpi-*.timer /etc/systemd/system/
|
|
cp /opt/wrolpi/etc/raspberrypios/wrolpi.target /etc/systemd/system/
|
|
# Copy MOTD scripts, delete original.
|
|
cp /opt/wrolpi/etc/raspberrypios/motd/20-wrolpi.motd /etc/update-motd.d/20-wrolpi
|
|
cp /opt/wrolpi/etc/raspberrypios/motd/30-wrolpi-first.motd /etc/update-motd.d/30-wrolpi
|
|
chmod +x /etc/update-motd.d/*
|
|
truncate -s 0 /etc/motd
|
|
|
|
# NetworkManager for the hotspot.
|
|
systemctl enable NetworkManager
|
|
|
|
# Enable iperf3 for speed testing.
|
|
systemctl enable iperf3
|
|
# Enable first startup script to generate certificates and start Caddy.
|
|
systemctl enable wrolpi-first-startup.service
|
|
# Enable Controller service to start on boot.
|
|
systemctl enable wrolpi-controller.service
|
|
# Apply controller.yaml drives.mounts at boot (replaces /etc/fstab for
|
|
# secondary mounts so the mount table travels with the drive).
|
|
systemctl enable wrolpi-mounts.service
|
|
# Enable weekly certificate renewal check.
|
|
systemctl enable wrolpi-cert-renew.timer
|
|
|
|
# Bootstrap service: on a Live USB it creates the persistence partition on
|
|
# first boot; on every boot (Live or Installed) it ensures the config
|
|
# directory exists and the wrolpi-* runtime services are enabled. The
|
|
# SQLite database is created by the API itself on first start (it lives in
|
|
# /media/wrolpi/config/wrolpi.db). Installed deployments find no live
|
|
# medium and short-circuit the partition step.
|
|
chmod +x /usr/local/sbin/wrolpi-bootstrap.sh
|
|
systemctl enable wrolpi-bootstrap.service
|
|
|
|
# Plymouth — replace Debian-branded splash with a minimal theme. live-build's
|
|
# initramfs regeneration at the end of the chroot phase will pick up this
|
|
# change so the new theme is used at boot.
|
|
plymouth-set-default-theme text || true
|
|
|
|
# LightDM greeter — add a WROLPi banner so the login screen identifies the
|
|
# system instead of looking like a stock Debian.
|
|
mkdir -p /etc/lightdm/lightdm-gtk-greeter.conf.d
|
|
cat > /etc/lightdm/lightdm-gtk-greeter.conf.d/50-wrolpi.conf <<'EOF'
|
|
[greeter]
|
|
banner-message-enable=true
|
|
banner-message-text=WROLPi
|
|
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/
|
|
|
|
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
|
|
chown -R root:root /opt/wrolpi-blobs
|
|
chmod 444 /opt/wrolpi-blobs/*
|
|
chattr +i /opt/wrolpi-blobs/*
|
|
fi
|
|
|
|
set +x
|
|
|
|
echo
|
|
echo "======================================================================"
|
|
echo "9999-wrolpi.hook.chroot completed"
|
|
echo "======================================================================"
|
|
echo
|