Files
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

179 lines
7.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BC-250 Console — local build → ISO
## Quick path: build-console.sh
```bash
cp console.env.example console.env # fill in usernames/passwords/display names
./build-console.sh # → iso-output/bootiso/bc250-console-gnome.iso
```
The script runs the whole verified pipeline below and bakes your accounts
(names, passwords, display names) and the console config into the ISO —
a fresh install needs no post-install setup beyond per-account logins
(Steam + Family View, Moonlight pairing, `sudo tailscale up`).
`console.env` is git-ignored: it contains real passwords, never commit it.
Everything below documents the manual pipeline the script automates.
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)
```bash
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`.)
```bash
# 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+.
```bash
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:
```bash
# 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):
```bash
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)
```bash
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.