#!/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 < files/console/etc/bc250-console.conf </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"