Move to Gitea: Gitea Actions workflow (BlueBuild CLI), registry git.lazypugs.com
bluebuild / Build Custom Image (push) Has been cancelled

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 12:29:48 -04:00
co-authored by Claude Fable 5
parent 0562266a7e
commit a54cb8df30
3 changed files with 84 additions and 62 deletions
+43 -25
View File
@@ -1,7 +1,8 @@
# 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 GHCR by GitHub Actions, and signed with cosign.
[BlueBuild](https://blue-build.org), published to the container registry on my Gitea instance
(**git.lazypugs.com**) by Gitea Actions, and signed with cosign.
- **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
@@ -20,29 +21,35 @@ 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.
## One-time setup (before first push)
## CI setup (Gitea Actions)
1. Create a GitHub repo and push this directory to it (`main` branch).
2. Generate the signing keypair in the repo root (**press Enter for an empty password** — the
build action cannot use an encrypted key):
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.
```bash
cosign generate-key-pair
```
Repo secrets (already configured):
3. Store the private key as an Actions secret and commit only the public half:
- `SIGNING_SECRET` — contents of `cosign.key` (generated with an empty password; the public half
is committed as `cosign.pub`). The CLI signs automatically on push when both are present.
- `REGISTRY_TOKEN` — a Gitea personal access token with **write:package** scope, used to push to
the registry. Gitea's automatic per-job token *cannot* publish packages (documented Gitea
limitation), hence the PAT. **Currently seeded with a temporary token — before revoking it,
create a durable PAT (Settings → Applications → Generate token, `write:package`) and update
the secret** (repo Settings → Actions → Secrets, or
`PUT /api/v1/repos/ckoch/main-desktop/actions/secrets/REGISTRY_TOKEN`).
```bash
gh secret set SIGNING_SECRET < cosign.key
git add cosign.pub && git commit -m "Add cosign public key" && git push
```
Runner requirements (act_runner on the instance):
`cosign.key` is git-ignored — never commit it.
4. The workflow (`.github/workflows/build.yml`) now builds on every push, on manual dispatch, and
daily at 06:00 UTC (so base-image updates flow through automatically — this is what makes the
image self-updating). Images publish to `ghcr.io/<your-github-user>/main-desktop`.
5. If the GHCR package ends up private, make it public in the package settings (Packages →
main-desktop → Package settings → Change visibility), or rebasing will fail to pull.
- **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
@@ -51,11 +58,11 @@ which contains the signing policy and public key), then signed:
```bash
# Step 1: unsigned rebase, then reboot
rpm-ostree rebase ostree-unverified-registry:ghcr.io/<your-github-user>/main-desktop:latest
rpm-ostree rebase ostree-unverified-registry:git.lazypugs.com/ckoch/main-desktop:latest
systemctl reboot
# Step 2: switch to the signed ref, then reboot
rpm-ostree rebase ostree-image-signed:docker://ghcr.io/<your-github-user>/main-desktop:latest
rpm-ostree rebase ostree-image-signed:docker://git.lazypugs.com/ckoch/main-desktop:latest
systemctl reboot
```
@@ -64,6 +71,14 @@ in the recipe, so `latest` never crosses a major until the recipe says so.
Roll back anytime with `rpm-ostree rollback` (or pick the previous deployment in the boot menu).
Notes for a self-hosted registry:
- The repo/package is public, so anonymous pulls work and the desktop needs no auth config. If
you ever make it private, the *host* needs credentials in `/etc/ostree/auth.json`
(containers-auth.json format) — `podman login` alone does not cover OS updates.
- Updates only flow while git.lazypugs.com is reachable; if the box is down, updates pause and
retry later. The running system is unaffected.
## Install-time checklist
1. **Driver sanity:** `nvidia-smi` reports driver **≥ 580** (currently 610.x) and the RTX 5090 is
@@ -72,11 +87,11 @@ Roll back anytime with `rpm-ostree rollback` (or pick the previous deployment in
2. **Signature:** verify the published image against the committed public key:
```bash
cosign verify --key cosign.pub ghcr.io/<your-github-user>/main-desktop:latest
cosign verify --key cosign.pub git.lazypugs.com/ckoch/main-desktop:latest
```
3. **Deployment:** `rpm-ostree status` shows the booted deployment is
`ostree-image-signed:docker://ghcr.io/<your-github-user>/main-desktop` and the base version
`ostree-image-signed:docker://git.lazypugs.com/ckoch/main-desktop` and the base version
matches a recent build.
4. **Flatpaks:** the first-boot service installs the whole list below; give it a few minutes on
first login (it notifies when done). Check with `flatpak list --system`.
@@ -181,5 +196,8 @@ no local hypervisor tooling in this image.
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 Actions tab; builds also run nightly, so a broken base shows up
there before it reaches the machine.
- **Check build status:** the repo's Actions tab; builds also run nightly, so a broken base
shows up there before it reaches the machine.
- **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.