- 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>
118 lines
4.7 KiB
Bash
Executable File
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"
|