Files
bc250-console/BUILD-CONSOLE.md
T
ckochandClaude Fable 5 83afbb7f87
Build Bazzite BC-250 / Check Bazzite channel digests (push) Has been cancelled
Build Bazzite BC-250 / Build Custom Image (push) Has been cancelled
Build Bazzite BC-250 / Build Custom 40CU Image (push) Has been cancelled
Build Bazzite BC-250 / Save Bazzite channel digest cache (push) Has been cancelled
Build Bazzite BC-250 / Publish GitHub Release (push) Has been cancelled
Add parent's operations manual (repo + baked at /usr/share/doc) and
document the Gitea OTA update path (bootc switch + publish routine)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 12:36:55 -04:00

6.7 KiB
Raw Blame History

BC-250 Console — local build → ISO

Custom recipe: recipes/bc250-console-gnome.yml (Bazzite GNOME + cyan-skillfish governor + SSH/RDP remote admin + BC-250 ttm kargs). Build path is local (no CI, no registry push, no cosign needed).

Two working paths: podman (BlueBuild's native path, use on a Fedora box) or docker (what was actually used for the first successful build, 2026-07-06, on Ubuntu 24.04 with a native dockerd). The docker path needs a few workarounds, all captured below.

Path A: podman (Fedora/bootc box)

bluebuild build ./recipes/bc250-console-gnome.yml

mkdir -p output
sudo podman run --rm -it --privileged \
  --security-opt label=type:unconfined_t \
  -v ./output:/output \
  -v ./iso-config.toml:/config.toml:ro \
  -v /var/lib/containers/storage:/var/lib/containers/storage \
  quay.io/centos-bootc/bootc-image-builder:latest \
  --type iso --rootfs btrfs \
  localhost/bc250-console-gnome:latest

Note: mount the image's GPG keys as in Path A step 4 if depsolve fails on terra-mesa (see below) — the same failure mode applies under podman.

Path B: docker (verified working)

Use a native dockerd, not Docker Desktop. Under Docker Desktop's VM, podman-in-docker cannot exec anything ("Invalid argument") and bind mounts outside the file-sharing allowlist are denied. A stock docker-ce daemon on the host kernel works. (Plain docker may point at the Desktop context — force the native daemon with docker -H unix:///var/run/docker.sock or docker context use default.)

# 1. Generate the Containerfile from the recipe (note: 'bluebuild' must be
#    given explicitly — the image entrypoint is dumb-init)
docker run --rm -v "$PWD":/bluebuild -w /bluebuild \
  ghcr.io/blue-build/cli:latest \
  bluebuild generate -o Containerfile ./recipes/bc250-console-gnome.yml

# 2. Build the image
docker buildx build -f Containerfile -t localhost/bc250-console-gnome:latest .

# 3. bootc-image-builder reads podman containers-storage, not the docker
#    store — copy the image over with skopeo via a throwaway local registry:
docker network create bibnet
docker run -d --name registry --network bibnet -p 127.0.0.1:5000:5000 registry:2
docker tag localhost/bc250-console-gnome:latest localhost:5000/bc250-console-gnome:latest
docker push localhost:5000/bc250-console-gnome:latest
docker volume create bib-storage
docker run --rm --privileged --network host \
  -v bib-storage:/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

# 4. Bazzite's terra repos reference GPG keys by file:// path; the depsolve
#    runs inside the bib container, so those keys must be mounted in:
cid=$(docker create localhost/bc250-console-gnome:latest true)
docker cp "$cid":/etc/pki/rpm-gpg ./rpm-gpg-keys
docker rm "$cid"

# 5. Build the ISO (--rootfs required: the image sets no root-fs-type;
#    iso-config.toml REQUIRED — the ISO installs unattended and the image has
#    no first-boot account wizard, so without baked users the install is
#    unloginable)
mkdir -p iso-output
docker run --rm --privileged --security-opt label=type:unconfined_t \
  -v "$PWD"/iso-output:/output \
  -v "$PWD"/rpm-gpg-keys:/etc/pki/rpm-gpg:ro \
  -v "$PWD"/iso-config.toml:/config.toml:ro \
  -v bib-storage:/var/lib/containers/storage \
  quay.io/centos-bootc/bootc-image-builder:latest \
  --type iso --rootfs btrfs \
  localhost/bc250-console-gnome:latest

Heads-up: the ISO wipes and auto-installs to the first disk with no prompts. Accounts come from iso-config.toml (placeholder passwords — change on first login: passwd, and sudo passwd kid).

ISO lands at iso-output/bootiso/install.iso (~5 GB), owned by root — fix with docker run --rm -v "$PWD"/iso-output:/o alpine chown -R 1000:1000 /o.

Kernel sanity check (before flashing)

Avoid kernels 6.15.06.15.6 and 6.17.86.17.10; prefer 6.18.x LTS / 6.17.11+.

docker run --rm localhost/bc250-console-gnome:latest rpm -q kernel

First successful build shipped kernel-7.0.9-ogc3.2.fc44 — fine.

Publish an update (OTA to the installed console)

The installed console follows git.lazypugs.com/ckoch/bc250-console-gnome:latest (one-time bootc switch after install — see below). To ship an update:

# rebuild the image (steps 12 above), then:
docker login git.lazypugs.com          # Gitea token with package write scope
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

The console's uupd timer picks it up automatically; to force it, SSH in and run sudo bootc upgrade && sudo systemctl reboot.

One-time, on the console after first install (points the OS at the registry instead of the offline install source):

sudo bootc switch git.lazypugs.com/ckoch/bc250-console-gnome:latest

If the Gitea package is private, the console needs pull credentials first: put a read-scope token in /etc/ostree/auth.json: {"auths":{"git.lazypugs.com":{"auth":"<base64 of user:token>"}}} — or make the package public in Gitea (Packages → bc250-console-gnome → Settings) and skip that.

Smoke test + install

  1. VM test: boot the ISO in a VM (KVM works headless: qemu-system-x86_64 -enable-kvm -m 8192 -drive file=vm.qcow2,if=virtio -cdrom <iso> -boot once=d). The embedded kickstart installs unattended. Validates composition and the installer only — not the BC-250 GPU/governor/Mesa path.
  2. Flash to USB (Fedora Media Writer / Impression / dd), install on the board. Black screen at install → "Install in Basic Graphics Mode".
  3. First boot, in the child's desktop session: run bc250-remote-setup, log into Steam, set Steam Family View, sudo tailscale up if using it.

On-hardware validation (board, not VM)

vulkaninfo | grep deviceName            # RADV GFX1013, NOT llvmpipe
systemctl status cyan-skillfish-governor-smu   # active
cat /sys/class/drm/card0/device/pp_dpm_sclk    # scaling present (may be card1)
sensors                                  # sane temps; watch backplate airflow
cat /proc/cmdline | tr ' ' '\n' | grep ttm     # ttm.pages_limit / page_pool_size

Then a real game for 30+ minutes for thermal/power stability.

Not baked into the image (per-board/per-user)

Modded BIOS + BIOS settings (512 MB dynamic VRAM, IOMMU off, auto power-on), RDP password/TLS cert, Steam login, Tailscale auth.

Security

  • SSH/RDP LAN- or tailnet-only. Never port-forward 22/3389.
  • If this ever moves to a registry (Gitea) for OTA updates: generate your own cosign keypair, re-add the signing module, and never reuse upstream's key.