Files
bc250-console/build-console.sh
T
ckochandClaude Fable 5 6194756d2a Bake Sunshine remote admin + add one-command configured ISO builder
- Sunshine flatpak in first-boot list; autostarts with the console
  account's session (bc250-sunshine-autostart, honors CONSOLE_KID_USER)
- bc250-personalize: one-shot display names from /etc/bc250-console.conf
- build-console.sh + console.env(.example): fill in usernames/passwords/
  display names, get a fully personalized ISO — no post-install steps
  beyond per-account logins. Generated files git-ignored (credentials)
- Docs: Moonlight is the remote-admin path; RDP marked blocked by the
  mutter cursor-metadata screencast crash on GFX1013

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 10:51:57 -04:00

118 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# One-command console ISO builder.
#
# cp console.env.example console.env # fill in names/passwords
# ./build-console.sh
#
# Produces iso-output/bootiso/bc250-console-gnome.iso with the accounts,
# display names, and console behavior fully baked — no post-install steps
# beyond per-account logins (Steam, Sunshine pairing, tailscale up).
#
# Pipeline (verified on Ubuntu 24.04 + Docker Desktop + native dockerd):
# BlueBuild generate -> docker build -> throwaway registry -> skopeo into
# a containers-storage volume -> bootc-image-builder ISO (native daemon).
set -euo pipefail
DIR="$(cd "$(dirname "$0")" && pwd)"
OUT="$(dirname "$DIR")/iso-output"
NATIVE="docker -H unix:///var/run/docker.sock"
cd "$DIR"
# --------------------------------------------------------------- config ----
[ -f console.env ] || {
cp console.env.example console.env
echo "Created console.env — fill in your names/passwords, then re-run."
exit 1
}
# shellcheck disable=SC1091
source ./console.env
for v in KID_USER KID_PASSWORD PARENT_USER PARENT_PASSWORD; do
[ -n "${!v:-}" ] || { echo "ERROR: $v is empty in console.env"; exit 1; }
done
case "$KID_PASSWORD$PARENT_PASSWORD" in *'"'*|*'\'*)
echo 'ERROR: passwords must not contain " or \'; exit 1;;
esac
echo ">> Building for kid='$KID_USER' parent='$PARENT_USER'"
cat > iso-config.generated.toml <<EOF
# GENERATED by build-console.sh from console.env — git-ignored, do not commit.
[[customizations.user]]
name = "$PARENT_USER"
password = "$PARENT_PASSWORD"
groups = ["wheel"]
[[customizations.user]]
name = "$KID_USER"
password = "$KID_PASSWORD"
EOF
mkdir -p files/console/etc
cat > files/console/etc/bc250-console.conf <<EOF
# GENERATED by build-console.sh — which accounts get the console treatment.
CONSOLE_KID_USER=$KID_USER
CONSOLE_KID_DISPLAY="${KID_DISPLAY:-}"
CONSOLE_PARENT_USER=$PARENT_USER
CONSOLE_PARENT_DISPLAY="${PARENT_DISPLAY:-}"
EOF
# ---------------------------------------------------------------- image ----
if ! docker info >/dev/null 2>&1; then
systemctl --user start docker-desktop 2>/dev/null || true
for _ in $(seq 1 24); do docker info >/dev/null 2>&1 && break; sleep 5; done
docker info >/dev/null 2>&1 || { echo "ERROR: docker daemon unavailable"; exit 1; }
fi
echo ">> Generating Containerfile"
docker run --rm -v "$PWD":/bluebuild -w /bluebuild ghcr.io/blue-build/cli:latest \
bluebuild generate -o Containerfile ./recipes/bc250-console-gnome.yml
echo ">> Building image"
docker buildx build -f Containerfile -t localhost/bc250-console-gnome:latest .
# ------------------------------------------ transfer to containers-storage -
echo ">> Staging image for bootc-image-builder"
docker network create bibnet 2>/dev/null || true
docker rm -f bc250-registry >/dev/null 2>&1 || true
docker run -d --name bc250-registry --network bibnet -p 127.0.0.1:5000:5000 registry:2 >/dev/null
docker tag localhost/bc250-console-gnome:latest localhost:5000/bc250-console-gnome:latest
docker push -q localhost:5000/bc250-console-gnome:latest
$NATIVE volume create bib-storage2 >/dev/null
$NATIVE run --rm --privileged --network host \
-v bib-storage2:/var/lib/containers/storage \
quay.io/skopeo/stable:latest copy --src-tls-verify=false \
docker://127.0.0.1:5000/bc250-console-gnome:latest \
containers-storage:localhost/bc250-console-gnome:latest
# terra repos reference GPG keys by file:// path; bib's depsolver needs them
if [ ! -d "$OUT/../rpm-gpg-keys" ]; then
echo ">> Extracting RPM GPG keys from image"
cid=$(docker create localhost/bc250-console-gnome:latest true)
docker cp "$cid":/etc/pki/rpm-gpg "$OUT/../rpm-gpg-keys"
docker rm "$cid" >/dev/null
fi
# ------------------------------------------------------------------ ISO ----
echo ">> Building ISO (this is the slow part)"
mkdir -p "$OUT"
$NATIVE run --rm --privileged --security-opt label=type:unconfined_t \
-v "$OUT":/output \
-v "$OUT/../rpm-gpg-keys":/etc/pki/rpm-gpg:ro \
-v "$PWD/iso-config.generated.toml":/config.toml:ro \
-v bib-storage2:/var/lib/containers/storage \
quay.io/centos-bootc/bootc-image-builder:latest \
--type iso --rootfs btrfs \
localhost/bc250-console-gnome:latest
$NATIVE run --rm -v "$OUT":/o alpine:latest chown -R "$(id -u):$(id -g)" /o
mv "$OUT/bootiso/install.iso" "$OUT/bootiso/bc250-console-gnome.iso"
( cd "$OUT/bootiso" && sha256sum bc250-console-gnome.iso > bc250-console-gnome.iso.sha256 )
docker rm -f bc250-registry >/dev/null
echo
echo ">> DONE: $OUT/bootiso/bc250-console-gnome.iso"
echo ">> Flash it, or publish the image for OTA updates:"
echo ">> docker login git.lazypugs.com && docker tag localhost/bc250-console-gnome:latest git.lazypugs.com/ckoch/bc250-console-gnome:latest && docker push git.lazypugs.com/ckoch/bc250-console-gnome:latest"