#!/usr/bin/env bash # # Smart Home Door-Panel ISO Builder # Target: builds a Debian 12 (Bookworm) live ISO on a Debian/Ubuntu build machine # # Drives `lb config && lb build` over hosts/door-panel/live-build/ to produce the # door/wardrobe panel described in docs/project-plan.md Phase 18: # - greetd autologin straight into a kiosk Sway session (no greeter UI) # - ONE Chromium kiosk window, default screen identity's dashboard.html (weather + # what-to-wear, who's home, groceries running low), "Show registration" on demand # - door-panel-agent (Python, systemd) — HA MQTT "Show home/registration" buttons # only; presence/weather/groceries/registration all come from identity's and # pantry-vision's own published APIs, called directly by the browser # - wyoming-satellite + openWakeWord for voice registration ("register me as # ") — opt-in like every other host's mic, but this device's whole point, # so expect it on for a real deployment # # Reuses hosts/thin-client's live-build toolchain and directory-split convention, not # its live-build tree — same relationship hosts/touch-panel, hosts/audio-endpoint, # and hosts/kitchen-display already have to the thin client's. Structurally this is # hosts/kitchen-display's twin: same one-workspace-two-kiosk-destinations shape, # different default content and a mic that's actually expected to be used. # # Run as: sudo -E tools/build-door-panel-iso.sh [hostname] # # Configuration comes from CoreSystemConfig.json — see tools/README.md. set -euo pipefail # --------------------------------------------------------------------------- # CONFIGURATION — comes from CoreSystemConfig.json, NOT from this file. # # There is nothing to edit here any more. Every value below is read from the one # config at the repo root, so an address or token can only be wrong in a single # place. Change it there and rebuild; see tools/README.md. # # sudo -E tools/build-door-panel-iso.sh # the only door-panel in the config # sudo -E tools/build-door-panel-iso.sh # a specific one, if several are defined # # The build refuses to start if the config is invalid (validate-config.py runs first), # so a typo costs seconds rather than a 40-minute build and a reboot. # --------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=lib/coreconfig.sh source "${SCRIPT_DIR}/lib/coreconfig.sh" core_select_kiosk "door-panel" "${1:-}" # Mapped onto this script's existing variable names, so everything below is unchanged # from when these were hand-edited constants. DEBIAN_RELEASE="$CORE_DEBIAN_RELEASE" KIOSK_USERNAME="$CORE_KIOSK_USERNAME" IMAGE_HOSTNAME="$CORE_KIOSK_HOSTNAME" KEYBOARD_LAYOUT="$CORE_KEYBOARD_LAYOUT" ENABLE_INSTALLER="$CORE_KIOSK_ENABLE_INSTALLER" MQTT_BROKER_HOST="$CORE_MQTT_BROKER_HOST" MQTT_BROKER_PORT="$CORE_MQTT_BROKER_PORT" MQTT_USERNAME="$CORE_MQTT_USERNAME" MQTT_PASSWORD="$CORE_MQTT_PASSWORD" SSH_AUTHORIZED_KEY="$CORE_SSH_AUTHORIZED_KEY" ENABLE_VOICE_SATELLITE="$CORE_KIOSK_VOICE_SATELLITE" VOICE_SATELLITE_NAME="$CORE_KIOSK_FRIENDLY_NAME" VOICE_WAKE_WORD="$CORE_KIOSK_WAKE_WORD" DOOR_PANEL_NAME="$CORE_KIOSK_FRIENDLY_NAME" # The HA area this device physically sits in, from the kiosk's `room` in # CoreSystemConfig.json. The agent publishes it as suggested_area so HA files # the device in the right room by itself — see docs/rooms-and-endpoints.md. DOOR_PANEL_ROOM="${CORE_KIOSK_ROOM:-}" IDENTITY_WEB_URL="$CORE_IDENTITY_WEB_URL" IDENTITY_URL="$CORE_IDENTITY_URL" IDENTITY_TOKEN="$CORE_IDENTITY_TOKEN" PANTRY_VISION_URL="$CORE_PANTRY_VISION_URL" PANTRY_VISION_TOKEN="$CORE_PANTRY_VISION_TOKEN" # --------------------------------------------------------------------------- # Paths — this script now lives in tools/, so the host directory it drives is # addressed from the repo root rather than relative to the script. # --------------------------------------------------------------------------- DOOR_PANEL_DIR="${CORE_REPO_ROOT}/hosts/door-panel" CONFIGS_DIR="${DOOR_PANEL_DIR}/configs" AGENT_DIR="${DOOR_PANEL_DIR}/agent" LIVE_BUILD_DIR="${DOOR_PANEL_DIR}/live-build" INCLUDES="${LIVE_BUILD_DIR}/config/includes.chroot" PACKAGE_LIST="${LIVE_BUILD_DIR}/config/package-lists/door-panel.list.chroot" # --------------------------------------------------------------------------- # Sanity checks # --------------------------------------------------------------------------- if [[ $EUID -ne 0 ]]; then echo "Warning: not running as root. 'lb build' needs root; re-run with: sudo $0" echo " Continuing anyway so you can at least regenerate includes.chroot..." fi if ! command -v lb &> /dev/null; then if [[ $EUID -eq 0 ]]; then echo "--- Installing live-build ---" apt-get update apt-get install -y live-build else echo "live-build is not installed and this script is not running as root." >&2 echo " Install it first: sudo apt-get install live-build" >&2 exit 1 fi else echo "--- live-build already installed, skipping ---" fi if [[ ! -f "$PACKAGE_LIST" ]]; then echo "Missing package list: $PACKAGE_LIST" >&2 exit 1 fi if [[ "$ENABLE_VOICE_SATELLITE" == "true" ]]; then echo "Note: ENABLE_VOICE_SATELLITE=true — this image expects a real microphone on" echo " the physical unit. Don't flash it to hardware that doesn't have one." fi echo echo "=== Smart Home Door-Panel ISO Builder ===" echo "Debian release : $DEBIAN_RELEASE" echo "Kiosk user : $KIOSK_USERNAME" echo "Image hostname : $IMAGE_HOSTNAME" echo "MQTT broker : ${MQTT_BROKER_HOST}:${MQTT_BROKER_PORT}" echo "identity-web : $IDENTITY_WEB_URL" echo "identity : $IDENTITY_URL" echo "pantry-vision : $PANTRY_VISION_URL" echo "Voice satellite : $ENABLE_VOICE_SATELLITE" echo "Keyboard layout : $KEYBOARD_LAYOUT" echo # --------------------------------------------------------------------------- # 1. Regenerate includes.chroot from configs/ and agent/ # --------------------------------------------------------------------------- echo "--- Regenerating $INCLUDES ---" rm -rf "$INCLUDES" mkdir -p \ "$INCLUDES/etc/greetd" \ "$INCLUDES/etc/door-panel-agent" \ "$INCLUDES/usr/local/bin" \ "$INCLUDES/opt/door-panel-agent" \ "$INCLUDES/home/${KIOSK_USERNAME}/.config/sway" \ "$INCLUDES/home/${KIOSK_USERNAME}/.ssh" subst() { sed -e "s/@KIOSK_USERNAME@/${KIOSK_USERNAME}/g" \ -e "s/@KEYBOARD_LAYOUT@/${KEYBOARD_LAYOUT}/g" "$1" > "$2" } subst "${CONFIGS_DIR}/greetd/config.toml" "$INCLUDES/etc/greetd/config.toml" subst "${CONFIGS_DIR}/sway/config" "$INCLUDES/home/${KIOSK_USERNAME}/.config/sway/config" subst "${AGENT_DIR}/door-panel-agent.service" "$INCLUDES/opt/door-panel-agent/door-panel-agent.service" install -m 0755 "${CONFIGS_DIR}/greetd/kiosk-session" "$INCLUDES/usr/local/bin/kiosk-session" install -m 0755 "${CONFIGS_DIR}/sway/home-kiosk" "$INCLUDES/usr/local/bin/home-kiosk" install -m 0755 "${CONFIGS_DIR}/sway/identity-kiosk" "$INCLUDES/usr/local/bin/identity-kiosk" mkdir -p "$INCLUDES/etc/default" cat > "$INCLUDES/etc/default/keyboard" < "$INCLUDES/home/${KIOSK_USERNAME}/.ssh/authorized_keys" chmod 600 "$INCLUDES/home/${KIOSK_USERNAME}/.ssh/authorized_keys" echo " Baked an SSH authorized_keys entry for ${KIOSK_USERNAME}." else echo " No SSH_AUTHORIZED_KEY set — SSH admin access will not be possible on this image." fi # --------------------------------------------------------------------------- # 2. Runtime config # --------------------------------------------------------------------------- echo "--- Writing /etc/door-panel-agent/config.env into includes.chroot ---" cat > "$INCLUDES/etc/door-panel-agent/config.env" <' and confirm it works." fi echo echo "Then pull the power on the container host and re-check: the panel must still" echo "boot (the dashboard will show connection errors, which is the expected degraded" echo "state — same acceptance already documented for hosts/touch-panel's Home" echo "workspace and hosts/kitchen-display's Scan/Inventory/Recipes tabs)." echo echo "Rebuilding later: edit hosts/door-panel/configs/* or agent/*, then re-run this" echo "script — includes.chroot is regenerated from them every time."