feat(packaging/bazzite): systemd-sysext replaces rpm-ostree layering as the primary install path

Layering is a last resort per the Bazzite docs (slows every OS update, can
block upgrades until removed); a sysext never enters an rpm-ostree
transaction, survives OS updates, and installs/updates with no reboot —
the mechanism Fedora Atomic ships via fedora-sysexts.

- build-sysext.sh wraps the built host+web RPMs into punktfunk-<V-R>-x86-64.raw:
  /etc payload relocated to /usr/share/punktfunk/etc (a sysext carries only
  /usr), the punktfunk-sysext helper embedded, ID=fedora + VERSION_ID pinned
  (merges on Bazzite via ID_LIKE; REFUSED after a major rebase instead of
  running soname-broken binaries — both behaviors validated live on Bazzite 43).
  SELinux labels are baked in as squashfs pseudo-xattrs from matchpathcon:
  unlabeled files run fine for user units but system daemons are DENIED
  (udev couldn't read the gamepad rule under enforcing) — validated on-glass.
  Refuses duplicate input package names (a stale noarch punktfunk-web next to
  the x86_64 one built a chimera image with the dead node launcher once).
- punktfunk-sysext.sh: install/update/status/remove against per-Fedora-major
  feeds (…/generic/punktfunk-sysext/f43[-canary]), SHA-256-verified, applies
  the udev/sysctl scriptlet work + /etc copies, prints the layering-migration
  hint. Live-validated on the .41 Bazzite box incl. service restart + web console.
- publish-sysext-feed.sh + rpm.yml: build + publish the image per matrix leg
  (fedver 43/44), canary feeds pruned to 6, stable release assets attached.
- update-punktfunk.sh warns when the sysext shadows a layered install.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 16:39:01 +00:00
parent 5b5ec15ead
commit 2190dad2ad
8 changed files with 539 additions and 75 deletions
+33 -26
View File
@@ -24,36 +24,43 @@ mid-stream. You flip between Gaming Mode and Desktop with Bazzite's normal Steam
## Install
The host ships as an RPM in punktfunk's **Gitea RPM registry** (public), so a Bazzite / Fedora
Atomic box layers and updates it with `rpm-ostree`. Add the repo, then layer the host plus the web
console and reboot:
The host installs as a **systemd system extension (sysext)** — no `rpm-ostree` layering. The
Bazzite docs treat layering as a last resort (layered packages slow every OS update and can block
upgrades until removed); a sysext never enters an rpm-ostree transaction: it overlays `/usr`
read-only from `/var/lib/extensions/`, survives OS updates, installs and updates **without a
reboot**, and is removable in one command. This is the same mechanism the Fedora Atomic
maintainers ship via the [fedora-sysexts](https://fedora-sysexts.github.io/) project.
```sh
# Add the repo. Packages are GPG-signed (gpgcheck=1, the packages@unom.io key) AND the repo
# metadata is Gitea-signed (repo_gpgcheck=1); gpgkey lists both keys so dnf imports each.
sudo tee /etc/yum.repos.d/punktfunk.repo >/dev/null <<'REPO'
[gitea-unom-bazzite]
name=punktfunk (unom, Bazzite)
baseurl=https://git.unom.io/api/packages/unom/rpm/bazzite
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://git.unom.io/api/packages/unom/rpm/repository.key
https://git.unom.io/api/packages/unom/generic/punktfunk-keys/1/RPM-GPG-KEY-punktfunk
REPO
# Layer the host + the web console, then reboot into the new deployment.
# (punktfunk Recommends punktfunk-web; list it explicitly so it's pulled regardless of weak-dep
# settings — the Gitea registry carries punktfunk-web, which COPR can't build.)
rpm-ostree install punktfunk punktfunk-web
systemctl reboot
# One-time bootstrap (afterwards the updater is on PATH as `punktfunk-sysext`):
curl -fsSLO https://git.unom.io/unom/punktfunk/raw/branch/main/packaging/bazzite/punktfunk-sysext.sh
sudo bash punktfunk-sysext.sh install # add `--channel canary` for rolling builds
```
`rpm-ostree upgrade` then tracks new builds automatically (Bazzite's auto-update timer does this
for you). For a fully baked appliance image there's also a **bootc** Containerfile that installs
the same RPMs from this registry — see `packaging/bootc/` and `packaging/rpm/README.md` in the repo.
Building from source works too (Bazzite is Fedora Atomic underneath, and its FFmpeg builds the host
fine — same steps as [Fedora KDE](/docs/fedora-kde)), but the registry is the supported path.
That downloads the newest image (host + tray + web console, SHA-256-verified over HTTPS from
punktfunk's package registry), merges it, and applies the udev/sysctl setup on the spot — the
host is usable immediately, no reboot. From then on:
```sh
sudo punktfunk-sysext update # fetch + merge the newest build
sudo punktfunk-sysext status # channel, installed vs latest version
sudo punktfunk-sysext remove # unmerge and delete — the box is back to stock
```
Two things to know:
- **After a Bazzite major rebase** (Fedora 43 → 44) the old image **refuses to load** rather than
run against mismatched system libraries — run `sudo punktfunk-sysext update` once and it fetches
the image built for the new base.
- **Already layering punktfunk?** Install the sysext (it shadows the layered copy immediately),
then drop the layer so it stops slowing your updates:
`sudo rpm-ostree uninstall punktfunk punktfunk-web && systemctl reboot`.
For a fully baked appliance image there's also a **bootc** Containerfile that installs the RPMs
from the registry at image-build time — see `packaging/bootc/` in the repo. Plain `rpm-ostree`
layering from the [RPM registry](https://git.unom.io/unom/-/packages) keeps working too (see
`packaging/bazzite/README.md`), but the sysext is the supported default. Building from source
also works (Bazzite is Fedora Atomic underneath — same steps as [Fedora KDE](/docs/fedora-kde)).
## Allow controller input