SmartestHome/tools/build-audio-endpoint-iso-am...

157 lines
6.8 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Builds the amd64 headless audio-endpoint ISO (mini PC + USB DAC/amp) with
# live-build — the same tool tools/build-thin-client-iso.sh
# drives, reused here rather than a new toolchain, per
# hosts/audio-endpoint/README.md's reasoning. Unlike that image, this one has
# no graphical/kiosk stack at all: it boots straight to multi-user.target with
# the shared spotify-connect.service running.
#
# One build per room: unlike the arm64 image (one generic .img, per-room
# identity set later via Raspberry Pi Imager), there is no equivalent
# post-build customisation tool for a generic x86 ISO, so IMAGE_HOSTNAME below
# is baked in at build time — same convention as the thin client's own
# THINCLIENT_NAME/IMAGE_HOSTNAME. Re-run this script once per room, changing
set -euo pipefail
# ---------------------------------------------------------------------------
# CONFIGURATION — comes from CoreSystemConfig.json, NOT from this file.
#
# Rooms are entries in the config's "audio_endpoints" list, so adding a second one is
# adding a list entry rather than editing and re-running this script with a different
# hostname — which is how per-room images drifted apart before.
#
# sudo -E tools/build-audio-endpoint-iso-amd64.sh # the only amd64 endpoint
# sudo -E tools/build-audio-endpoint-iso-amd64.sh <hostname> # a specific one
# ---------------------------------------------------------------------------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib/coreconfig.sh
source "${SCRIPT_DIR}/lib/coreconfig.sh"
core_select_audio_endpoint amd64 "${1:-}"
DEBIAN_RELEASE="$CORE_DEBIAN_RELEASE"
IMAGE_HOSTNAME="$CORE_AUDIO_HOSTNAME" # also the Spotify Connect device name
# ---------------------------------------------------------------------------
# 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.
# ---------------------------------------------------------------------------
AUDIO_ENDPOINT_DIR="${CORE_REPO_ROOT}/hosts/audio-endpoint"
SHARED_CONFIGS_DIR="$AUDIO_ENDPOINT_DIR/configs"
LIVE_BUILD_DIR="${AUDIO_ENDPOINT_DIR}/live-build-amd64"
INCLUDES="${LIVE_BUILD_DIR}/config/includes.chroot"
PACKAGE_LIST="${LIVE_BUILD_DIR}/config/package-lists/audio-endpoint.list.chroot"
# ---------------------------------------------------------------------------
# Sanity checks
# ---------------------------------------------------------------------------
if [[ $EUID -ne 0 ]]; then
echo "Warning: not running as root. 'lb build' needs root to bootstrap and chroot,"
echo " and will fail partway through. Re-run with: sudo $0"
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
fi
if [[ ! -f "$PACKAGE_LIST" ]]; then
echo "Missing package list: $PACKAGE_LIST" >&2
exit 1
fi
for f in spotify-connect.service spotify-connect-start; do
if [[ ! -f "$SHARED_CONFIGS_DIR/$f" ]]; then
echo "Missing $SHARED_CONFIGS_DIR/$f — is this script running from a full checkout?" >&2
exit 1
fi
done
# ---------------------------------------------------------------------------
# 1. Regenerate includes.chroot from the shared configs/
# ---------------------------------------------------------------------------
echo "--- Regenerating $INCLUDES ---"
rm -rf "$INCLUDES"
install -d \
"$INCLUDES/etc/systemd/system" \
"$INCLUDES/usr/local/bin"
install -m 0644 "${SHARED_CONFIGS_DIR}/spotify-connect.service" \
"$INCLUDES/etc/systemd/system/spotify-connect.service"
install -m 0755 "${SHARED_CONFIGS_DIR}/spotify-connect-start" \
"$INCLUDES/usr/local/bin/spotify-connect-start"
# ---------------------------------------------------------------------------
# 2. lb config
# ---------------------------------------------------------------------------
cd "$LIVE_BUILD_DIR"
chmod +x config/hooks/normal/*.hook.chroot
if [[ -e .build ]]; then
echo "--- Previous build found, running 'lb clean' (package cache is kept) ---"
lb clean
fi
echo "--- Running lb config ---"
# live-build auto-discovers config/package-lists/*.list.chroot and
# config/hooks/normal/*.hook.chroot; there is no flag to point at them
# individually — same convention as hosts/thin-client's own build script.
lb config \
--distribution "$DEBIAN_RELEASE" \
--architectures amd64 \
--linux-flavours amd64 \
--archive-areas "main contrib non-free-firmware" \
--binary-images iso-hybrid \
--debian-installer none \
--iso-application "SmartestHome Audio Endpoint" \
--iso-publisher "SmartestHome" \
--iso-volume "smarthome-audio-endpoint" \
--memtest none \
--bootappend-live "boot=live components quiet hostname=${IMAGE_HOSTNAME}"
# ---------------------------------------------------------------------------
# 3. lb build
# ---------------------------------------------------------------------------
echo "--- Running lb build (this takes a while and needs network) ---"
lb build
ISO_PATH="$(find "$LIVE_BUILD_DIR" -maxdepth 1 -name '*.iso' -print -quit)"
ISO_PATH="${ISO_PATH:-${LIVE_BUILD_DIR}/live-image-amd64.hybrid.iso}"
# Per-room name: unlike the arm64 image below, amd64 bakes the hostname in at build
# time (there is no x86 equivalent of Pi Imager's OS Customisation), so each room is a
# genuinely different ISO and they must not share a filename.
ISO_PATH="$(core_publish_image "$ISO_PATH" "audio-endpoint" "$IMAGE_HOSTNAME")"
echo
echo "=== Done ==="
echo "ISO written to:"
echo " ${ISO_PATH}"
echo
echo "What's in it:"
echo " Hostname / Spotify Connect device name: ${IMAGE_HOSTNAME}"
echo " No graphical stack — boots straight to multi-user.target"
echo " spotify-connect.service — see hosts/audio-endpoint/README.md"
echo
echo "Next steps:"
echo " 1. Write the ISO to a USB stick (dd, Rufus, Balena Etcher, whatever you"
echo " normally use) and leave it live-booting from that stick, same as the"
echo " thin client — this image does not install itself to disk."
echo " 2. Attach the USB DAC/amp and passive speakers, connect Ethernet or"
echo " configure Wi-Fi via nmtui after first boot (no display attached, so"
echo " do this over SSH — openssh-server is enabled)."
echo " 3. First boot checklist (see README.md for the full unverified list):"
echo " systemctl status spotify-connect"
echo " aplay -l # find the USB DAC's card index — see README's amd64 section"
echo " # confirm '${IMAGE_HOSTNAME}' shows up as a Spotify Connect device"
echo " 4. Building for another room? Edit IMAGE_HOSTNAME at the top of this"
echo " script and re-run — each room needs its own build."