Local build path: pinned alt-tags, manual-only workflow, README build docs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 13:25:52 -04:00
co-authored by Claude Fable 5
parent a54cb8df30
commit 7f0a30c01f
4 changed files with 53 additions and 25 deletions
+39 -18
View File
@@ -1,8 +1,9 @@
# main-desktop
Custom [Bazzite DX](https://github.com/ublue-os/bazzite-dx) image for my desktop, built with
[BlueBuild](https://blue-build.org), published to the container registry on my Gitea instance
(**git.lazypugs.com**) by Gitea Actions, and signed with cosign.
[BlueBuild](https://blue-build.org), published signed (cosign) to the container registry on my
Gitea instance (**git.lazypugs.com**) — built locally today, Gitea Actions-ready when a runner
is registered.
- **Base:** `ghcr.io/ublue-os/bazzite-dx-nvidia` — Bazzite DX, KDE Plasma, **NVIDIA open kernel
modules**. There is no separate `-open` DX image anymore: DX NVIDIA is open-driver-only, which
@@ -21,12 +22,37 @@ in-image, the whole custom layer is "install these Flatpaks on first boot + trus
which the `default-flatpaks` and `signing` modules express declaratively in ~40 lines of YAML —
no hand-rolled first-boot systemd unit needed.
## CI setup (Gitea Actions)
## Building & publishing
The workflow lives at [.gitea/workflows/build.yml](.gitea/workflows/build.yml) and runs the
**BlueBuild CLI** directly (the `blue-build/github-action` is GitHub-only). It builds on push,
manual dispatch, and daily at 06:00 UTC so base-image updates flow through automatically — that
schedule is what makes the image self-updating.
### Locally (current path)
The image is built and pushed from a workstation with the BlueBuild CLI driving Docker. From
the repo root (needs `cosign.key` present there, and ~25 GB free for layers):
```bash
# One-time CLI install (extracts a static binary to /usr/local/bin/bluebuild):
docker run --pull always --rm ghcr.io/blue-build/cli:latest-installer | bash
# Build, push, and sign in one shot:
BB_USERNAME=ckoch BB_PASSWORD=<gitea-PAT-with-write:package> \
bluebuild build --push --retry-push \
--registry git.lazypugs.com --registry-namespace ckoch \
recipes/recipe.yml
```
Tags are pinned in the recipe (`alt-tags: latest, stable-44`), so the pushed refs are the same
no matter where the build runs. Signing happens automatically because `cosign.pub` is in the
repo root and the key is available. **Rebuild cadence is manual under this model** — run the
build when you want base-image updates rolled in; the OS then picks them up on its normal
update timer.
### Gitea Actions (optional, needs a runner)
[.gitea/workflows/build.yml](.gitea/workflows/build.yml) runs the same **BlueBuild CLI** build
(the `blue-build/github-action` is GitHub-only). It is currently `workflow_dispatch`-only
because no Actions runner is registered on the instance; when one exists, restore the
commented-out `schedule` + `push` triggers in the workflow to make builds fully automatic
(daily rebuilds = true self-updating).
Repo secrets (already configured):
@@ -39,18 +65,13 @@ Repo secrets (already configured):
the secret** (repo Settings → Actions → Secrets, or
`PUT /api/v1/repos/ckoch/main-desktop/actions/secrets/REGISTRY_TOKEN`).
Runner requirements (act_runner on the instance):
Runner requirements when you set one up (act_runner):
- **Privileged job containers must be allowed** — the build runs buildah inside the job
container (`ghcr.io/blue-build/cli`). In the runner's `config.yaml`:
`container: { privileged: true }`. Without it the build fails at the buildah stage.
- Internet access (pulls the multi-GB Bazzite base from ghcr.io) and ~25+ GB free scratch disk.
Known first-run watch-items (verified docs, but no public precedent for this exact stack):
cosign signature push to a Gitea registry and the CLI's tag generation under act_runner's
GitHub-compat env are both expected to work but unproven in the wild — if the first run fails
at signing or tagging, that's where to look, not the recipe.
## Rebasing the desktop onto this image
From the existing Bazzite install, rebase in two steps — first unsigned (this installs the image,
@@ -192,12 +213,12 @@ no local hypervisor tooling in this image.
## Maintenance
- **Change the Flatpak list / packages:** edit [recipes/recipe.yml](recipes/recipe.yml), push,
and the next update picks it up. (Removing an app from the list does not uninstall it from the
machine; `flatpak uninstall` it once by hand.)
rebuild (see "Building & publishing"), and the next OS update picks it up. (Removing an app
from the list does not uninstall it from the machine; `flatpak uninstall` it once by hand.)
- **Jump Fedora majors:** change `image-version: stable-44` → `stable-45` in the recipe when
ready, push, then update normally.
- **Check build status:** the repo's Actions tab; builds also run nightly, so a broken base
shows up there before it reaches the machine.
ready, rebuild, then update normally.
- **Pull in base-image updates:** just rebuild — the base tag is `stable-44`, so each rebuild
picks up the newest Bazzite build within Fedora 44.
- **Key hygiene:** `cosign.key` is git-ignored and lives only on the workstation + in the
`SIGNING_SECRET` secret — keep a backup (password manager). Losing it means generating a new
pair, updating the secret, and re-doing the two-step rebase to re-establish trust.