#!/usr/bin/env bash # # Build EVERY image this household needs, from one CoreSystemConfig.json. # # This is the normal way to use tools/. The individual builders still exist and still # work, but rebuilding one image on its own is the unusual case: the images are a set # that has to agree with itself, and the whole reason a kiosk knows the container # host's address is that both were generated in the same pass from the same file. # Building the set is therefore the default, and building one is the exception. # # sudo -E tools/build-all.sh # the core pair + every configured kiosk # sudo -E tools/build-all.sh --core # just the twinned pair # sudo -E tools/build-all.sh --kiosks # just the kiosks # sudo -E tools/build-all.sh --dry-run # validate + list what would be built # # Every image is stamped with the same pair ID, so a drawer full of USB sticks can be # checked against each other later: same ID means they were built from the same # config and agree on every address and token. # # WHAT COMES OUT CONTAINS SECRETS. Wi-Fi PSK, service tokens, MQTT and HA credentials # are burnt into these images — that is the point (nothing to configure post-install), # and it makes every ISO a credential. .gitignore keeps them out of the repo; wiping # old USB sticks is on you. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=lib/coreconfig.sh source "${SCRIPT_DIR}/lib/coreconfig.sh" MODE="all" DRY_RUN="false" for arg in "$@"; do case "$arg" in --core) MODE="core" ;; --kiosks) MODE="kiosks" ;; --dry-run) DRY_RUN="true" ;; -h|--help) sed -n '2,25p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; *) core_die "Unknown argument '$arg'. Try --help." ;; esac done core_load [[ "$DRY_RUN" == "true" ]] || core_require_root "$@" PAIR_ID="$(core_pair_id)" # Which kiosks are configured, and which builder each needs. mapfile -t KIOSK_ROWS < <(python3 - "$CORE_CONFIG_PATH" <<'PY' import json, sys for k in json.load(open(sys.argv[1])).get("kiosks", []): print(f"{k['type']}\t{k['hostname']}\t{k.get('friendly_name','')}") PY ) # Audio endpoints, with the architecture each one needs. Both architectures are built # when both are configured — they're two different toolchains producing two different # artifacts (an amd64 ISO and an arm64 .img), not one image that runs on both. mapfile -t AUDIO_ROWS < <(python3 - "$CORE_CONFIG_PATH" <<'PY' import json, sys for a in json.load(open(sys.argv[1])).get("audio_endpoints", []): print(f"{a['arch']}\t{a['hostname']}\t{a.get('friendly_name','')}") PY ) cat </dev/null | tail -n +2 | awk '{printf " %-52s %s\n", $9, $5}' || true cat <