feat: generic user, dynamic paths, simplified ISO build pipeline
This commit is contained in:
+109
-104
@@ -1,119 +1,124 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Build SeniorNet Kiosk ISO
|
||||
# Run on workstation: ./build-iso.sh
|
||||
# Requires: debian-live-build, sudo
|
||||
|
||||
echo "==> SeniorNet Kiosk ISO Builder"
|
||||
echo
|
||||
# SeniorNet Kiosk ISO Builder
|
||||
# Takes the official Debian Trixie netinstall ISO and repacks it with:
|
||||
# - preseed.cfg embedded for silent auto-install
|
||||
# - GRUB + isolinux configured for auto-boot (UEFI + BIOS)
|
||||
#
|
||||
# The kiosk app itself is NOT bundled — it's downloaded from Gitea at
|
||||
# first-boot time. Rebuild the ISO only when changing Debian base or preseed.
|
||||
#
|
||||
# Run: sudo ./build-iso.sh
|
||||
# Output: iso-output/seniornet-kiosk.iso
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "ERROR: Run as root (sudo ./build-iso.sh)"
|
||||
exit 1
|
||||
echo "ERROR: Run as root: sudo ./build-iso.sh"; exit 1
|
||||
fi
|
||||
|
||||
# Check dependencies
|
||||
if ! command -v lb &>/dev/null; then
|
||||
echo "==> Installing debian-live-build..."
|
||||
apt-get update
|
||||
apt-get install -y debian-live-build
|
||||
fi
|
||||
|
||||
BUILD_DIR="/tmp/kiosk-build-$$"
|
||||
OUTPUT_DIR="$(pwd)/iso-output"
|
||||
REPO_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
OUTPUT_DIR="$REPO_DIR/iso-output"
|
||||
WORK_DIR="$(mktemp -d /tmp/kiosk-iso-XXXX)"
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
mkdir -p "$BUILD_DIR" "$OUTPUT_DIR"
|
||||
cd "$BUILD_DIR"
|
||||
DEBIAN_ISO_URL="https://cdimage.debian.org/cdimage/daily-builds/daily/arch-latest/amd64/iso-cd/debian-testing-amd64-netinst.iso"
|
||||
ISO_CACHE="$OUTPUT_DIR/debian-netinst.iso"
|
||||
OUTPUT_ISO="$OUTPUT_DIR/seniornet-kiosk.iso"
|
||||
|
||||
echo "==> Initializing live-build..."
|
||||
lb config \
|
||||
--distribution trixie \
|
||||
--architectures amd64 \
|
||||
--image-type iso-hybrid \
|
||||
--bootappend-live "boot=live components autologin username=root quiet splash" \
|
||||
--bootappend-install "preseed/file=/preseed.cfg auto=true priority=critical" \
|
||||
--linux-packages "linux-image-amd64" \
|
||||
--parent-mirror-bootstrap "https://deb.debian.org/debian" \
|
||||
--parent-mirror-binary "https://deb.debian.org/debian" \
|
||||
--parent-mirror-binary-security "https://security.debian.org/debian-security" \
|
||||
--parent-distribution-binary-security trixie-security
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
echo "==> Adding packages..."
|
||||
mkdir -p config/package-lists
|
||||
cat > config/package-lists/kiosk.list.chroot << 'PKGLIST'
|
||||
# Base system
|
||||
openssh-server
|
||||
build-essential
|
||||
git
|
||||
curl
|
||||
wget
|
||||
sudo
|
||||
|
||||
# Display and window manager
|
||||
xserver-xorg
|
||||
xserver-xorg-video-dummy
|
||||
xinit
|
||||
openbox
|
||||
xvfb
|
||||
xdotool
|
||||
xprop
|
||||
|
||||
# Chromium browser
|
||||
chromium
|
||||
|
||||
# Python and kiosk app
|
||||
python3
|
||||
python3-pip
|
||||
sqlite3
|
||||
PKGLIST
|
||||
|
||||
echo "==> Adding preseed file..."
|
||||
mkdir -p config/includes.installer
|
||||
cp "$REPO_DIR/preseed.cfg" config/includes.installer/
|
||||
|
||||
echo "==> Adding hook script..."
|
||||
mkdir -p config/hooks/normal
|
||||
cat > config/hooks/normal/9999-kiosk-postinstall.chroot << 'HOOK'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "==> Running kiosk post-install hook..."
|
||||
|
||||
# Install Python packages
|
||||
pip3 install --break-system-packages PyQt5 websocket-client
|
||||
|
||||
# Clone repo
|
||||
if [ ! -d /home/jgitta/kiosk-browser ]; then
|
||||
git clone https://gitea.jgitta.com/jgitta/senior-kiosk.git /home/jgitta/kiosk-browser
|
||||
cd /home/jgitta/kiosk-browser
|
||||
bash install-kiosk.sh
|
||||
# ── Dependencies ───────────────────────────────────────────────────
|
||||
echo "==> Checking dependencies..."
|
||||
MISSING=""
|
||||
for pkg in xorriso isolinux curl; do
|
||||
dpkg -l "$pkg" &>/dev/null || MISSING="$MISSING $pkg"
|
||||
done
|
||||
if [ -n "$MISSING" ]; then
|
||||
apt-get install -y $MISSING
|
||||
fi
|
||||
|
||||
echo "==> Kiosk post-install complete"
|
||||
HOOK
|
||||
chmod +x config/hooks/normal/9999-kiosk-postinstall.chroot
|
||||
|
||||
echo "==> Building ISO (this may take 5-10 minutes)..."
|
||||
lb build 2>&1 | tail -20
|
||||
|
||||
ISO_FILE="live-image-amd64.hybrid.iso"
|
||||
if [ -f "$ISO_FILE" ]; then
|
||||
cp "$ISO_FILE" "$OUTPUT_DIR/seniornet-kiosk.iso"
|
||||
echo
|
||||
echo "==> ✓ ISO build complete!"
|
||||
echo " Output: $OUTPUT_DIR/seniornet-kiosk.iso"
|
||||
echo
|
||||
echo "Next steps:"
|
||||
echo " 1. Write to USB:"
|
||||
echo " sudo dd if=$OUTPUT_DIR/seniornet-kiosk.iso of=/dev/sdX bs=4M status=progress && sync"
|
||||
echo
|
||||
echo " 2. Boot from USB and wait ~10 minutes for silent installation"
|
||||
echo
|
||||
echo " 3. Machine will reboot into kiosk mode automatically"
|
||||
echo
|
||||
# ── Download Debian netinstall ISO (cached) ────────────────────────
|
||||
if [ -f "$ISO_CACHE" ]; then
|
||||
echo "==> Using cached Debian ISO: $ISO_CACHE"
|
||||
else
|
||||
echo "ERROR: ISO build failed"
|
||||
exit 1
|
||||
echo "==> Downloading Debian Trixie netinstall (~700 MB)..."
|
||||
curl -L --progress-bar "$DEBIAN_ISO_URL" -o "$ISO_CACHE"
|
||||
fi
|
||||
|
||||
# ── Extract ISO ────────────────────────────────────────────────────
|
||||
echo "==> Extracting ISO..."
|
||||
mkdir -p "$WORK_DIR/iso"
|
||||
xorriso -osirrox on -indev "$ISO_CACHE" -extract / "$WORK_DIR/iso" 2>/dev/null
|
||||
chmod -R u+w "$WORK_DIR/iso"
|
||||
|
||||
# ── Add preseed to ISO root ────────────────────────────────────────
|
||||
# Accessible during install as /cdrom/preseed.cfg
|
||||
cp "$REPO_DIR/preseed.cfg" "$WORK_DIR/iso/preseed.cfg"
|
||||
|
||||
# ── Auto-boot: GRUB (UEFI) ────────────────────────────────────────
|
||||
echo "==> Configuring auto-boot..."
|
||||
cat > "$WORK_DIR/iso/boot/grub/grub.cfg" << 'GRUBEOF'
|
||||
set default=0
|
||||
set timeout=5
|
||||
|
||||
menuentry "SeniorNet Kiosk — Automatic Install" {
|
||||
linux /install.amd/vmlinuz preseed/file=/cdrom/preseed.cfg auto=true priority=critical quiet ---
|
||||
initrd /install.amd/initrd.gz
|
||||
}
|
||||
|
||||
menuentry "SeniorNet Kiosk — Install (verbose)" {
|
||||
linux /install.amd/vmlinuz preseed/file=/cdrom/preseed.cfg auto=true priority=critical ---
|
||||
initrd /install.amd/initrd.gz
|
||||
}
|
||||
GRUBEOF
|
||||
|
||||
# ── Auto-boot: isolinux (BIOS legacy) ─────────────────────────────
|
||||
if [ -f "$WORK_DIR/iso/isolinux/isolinux.cfg" ]; then
|
||||
cat > "$WORK_DIR/iso/isolinux/isolinux.cfg" << 'ISOEOF'
|
||||
default install
|
||||
timeout 50
|
||||
|
||||
label install
|
||||
menu label SeniorNet Kiosk - Automatic Install
|
||||
kernel /install.amd/vmlinuz
|
||||
append initrd=/install.amd/initrd.gz preseed/file=/cdrom/preseed.cfg auto=true priority=critical quiet ---
|
||||
|
||||
label verbose
|
||||
menu label SeniorNet Kiosk - Install (verbose)
|
||||
kernel /install.amd/vmlinuz
|
||||
append initrd=/install.amd/initrd.gz preseed/file=/cdrom/preseed.cfg auto=true priority=critical ---
|
||||
ISOEOF
|
||||
fi
|
||||
|
||||
# ── Repack ISO (UEFI + BIOS hybrid) ───────────────────────────────
|
||||
echo "==> Building final ISO..."
|
||||
cd "$WORK_DIR/iso"
|
||||
|
||||
xorriso -as mkisofs \
|
||||
-r -J -joliet-long \
|
||||
-V "SeniorNet Kiosk" \
|
||||
--grub2-mbr boot/grub/i386-pc/boot_hybrid.img \
|
||||
-partition_offset 16 \
|
||||
--mbr-force-bootable \
|
||||
-append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b boot/grub/efi.img \
|
||||
-appended_part_as_gpt \
|
||||
-iso_mbr_part_type a2a0d0ebe5b9334487c068b6b72699c7 \
|
||||
-c '/boot/boot.cat' \
|
||||
-b '/boot/grub/i386-pc/eltorito.img' \
|
||||
-no-emul-boot -boot-load-size 4 -boot-info-table --grub2-boot-info \
|
||||
-eltorito-alt-boot \
|
||||
-e '--interval:appended_partition_2:::' \
|
||||
-no-emul-boot \
|
||||
-o "$OUTPUT_ISO" \
|
||||
. 2>&1 | tail -5
|
||||
|
||||
echo
|
||||
SIZE=$(du -sh "$OUTPUT_ISO" | cut -f1)
|
||||
echo "==> ✓ ISO complete: $OUTPUT_ISO ($SIZE)"
|
||||
echo
|
||||
echo "Write to USB:"
|
||||
echo " sudo dd if=\"$OUTPUT_ISO\" of=/dev/sdX bs=4M status=progress && sync"
|
||||
echo
|
||||
echo "Boot from USB — Debian installs silently (~10 min) then reboots."
|
||||
echo "On first reboot: setup wizard prompts for username and senior's name."
|
||||
echo "Second reboot: kiosk is running."
|
||||
|
||||
Reference in New Issue
Block a user