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
document the Gitea OTA update path (bootc switch + publish routine) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
164 lines
6.7 KiB
Markdown
164 lines
6.7 KiB
Markdown
# 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)
|
||
|
||
```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.0–6.15.6 and 6.17.8–6.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 1–2 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.
|