feat(steamdeck): self-healing reliability — post-OS-update rebuild check + script/docs polish

- rebuild-check.sh + punktfunk-rebuild-check.service (enabled, ordered
  Before=punktfunk-host): ldd-probes the host binary at session start —
  milliseconds when healthy, a full update.sh rebuild only when a
  SteamOS update actually broke its library links. update.sh restarts
  go --no-block so the check → update.sh → restart chain can't deadlock
  against the unit ordering. update.sh retrofits the unit.
- installer summary: web console is https (the unit serves TLS).
- docs: steamos-host.md (runner in the build step, keep-list + auto
  rebuild = updates survive hands-free), gamescope.md (Gaming Mode
  touch = single-finger pointer, exact taps, no multi-touch),
  plugins.mdx (SteamOS runner note), scripts/steamdeck/README.md
  (rebuild-check, runner payload, keep list, honest packaging
  trade-off + the CI-prebuilt future direction).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 11:56:09 +02:00
co-authored by Claude Fable 5
parent 35923080fb
commit acce43ebbf
7 changed files with 133 additions and 16 deletions
+28 -7
View File
@@ -22,6 +22,15 @@ is only the build environment; `punktfunk-host` is launched directly, not via `d
rebuild always matches the running OS. Encode is **VAAPI** on the Deck's AMD GPU (NVENC on NVIDIA),
auto-selected by `PUNKTFUNK_ENCODER=auto`.
The honest trade-off: on-device building costs a slow first install (~1015 min, ~1 GB of image +
toolchain) and adds moving parts (apt mirrors, rustup, bun) — the price of an install that can
always chase the OS. Both failure modes of that chase are automated away now:
`punktfunk-rebuild-check` rebuilds when an OS update breaks the binary's links, and the
atomic-update keep list preserves the `/etc` tuning. The eventual lighter-weight alternative is a
CI-prebuilt bundle with the volatile libraries (FFmpeg et al.) vendored under an `$ORIGIN` rpath —
OS-update-proof without a toolchain on the device — worth it once SteamOS host volume justifies
per-release artifact signing/hosting; the from-source path would stay as the dev/fallback route.
The web console is the one part that stays in the container at runtime: it's a Nitro **`bun`**
build (`bun` both builds **and runs** it — the bun-preset output uses `Bun.serve` with TLS,
serving HTTPS (HTTP/1.1 over TLS) with the host's identity cert), so its service does
@@ -31,8 +40,9 @@ serving HTTPS (HTTP/1.1 over TLS) with the host's identity cert), so its service
| Script | What it does |
|--------|--------------|
| `install.sh` | Idempotent installer: ensure the `pf2` distrobox + toolchain → build host (+web) → write config → tune sysctl + `input` group (sudo) → install + start `punktfunk-host` / `punktfunk-web` systemd **user** services with linger. |
| `update.sh` | Rebuild from the current source and restart the services (config + pairings persist). `--pull` does `git pull` first. |
| `install.sh` | Idempotent installer: ensure the `pf2` distrobox + toolchain → build host + web + **plugin runner** → write config → tune sysctl + udev + `vhci-hcd` + `input` group and **register it on SteamOS's atomic-update keep list** (sudo) → install + start `punktfunk-host` / `punktfunk-web` systemd **user** services with linger, plus the **rebuild check** below. |
| `update.sh` | Rebuild everything from the current source and restart the services (config + pairings persist). `--pull` does `git pull` first. Also retrofits anything a newer install.sh writes (runner, keep-list registration, rebuild check) onto older installs. |
| `rebuild-check.sh` | The post-OS-update self-heal (run by `punktfunk-rebuild-check.service` before the host at session start): `ldd`-probes the binary — milliseconds when healthy, a full `update.sh` rebuild only when a SteamOS update actually broke its library links. |
```sh
git clone https://git.unom.io/unom/punktfunk ~/punktfunk
@@ -57,10 +67,19 @@ default `pf2`), `PUNKTFUNK_MGMT_PORT` (47990), `PUNKTFUNK_WEB_PORT` (47992).
here too and persists across updates.
- **Services:** `~/.config/systemd/user/punktfunk-host.service` (runs `serve --gamestream --mgmt-bind
0.0.0.0:47990`, `+ --open` if chosen — `--gamestream` adds the Moonlight-compat planes so the Deck's
Game Mode also streams to stock Moonlight; the native `punktfunk/1` plane is always on) and
`punktfunk-web.service`. Linger is enabled so they run without a login session.
Game Mode also streams to stock Moonlight; the native `punktfunk/1` plane is always on),
`punktfunk-web.service`, `punktfunk-rebuild-check.service` (post-OS-update self-heal, enabled), and
`punktfunk-scripting.service` (plugin runner, **opt-in** — enable it once you use plugins/scripts).
Linger is enabled so they run without a login session.
- **Plugin runner:** the deb's payload laid out user-scoped (read-only `/usr` can't take the
package): wrapper `~/.local/bin/punktfunk-scripting`, pinned `bun` in
`~/.local/lib/punktfunk-scripting/`, bundle in `~/.local/share/punktfunk-scripting/`.
- **System tuning (sudo):** `/etc/sysctl.d/99-punktfunk-net.conf` (32 MB UDP buffers — the #1
high-bitrate lever), `/etc/udev/rules.d/60-punktfunk.rules`, and `$USER` in the `input` group.
high-bitrate lever), `/etc/udev/rules.d/60-punktfunk.rules` (`uinput`/`uhid` access),
`/etc/modules-load.d/punktfunk.conf` (`vhci-hcd` for the native Deck pad), `$USER` in the `input`
group — and `/etc/atomic-update.conf.d/punktfunk.conf`, which registers the three files on
SteamOS's atomic-update keep list so A/B OS updates carry them over (verified: without it an
update silently strips them — pads degrade to Xbox 360, buffers drop to 208 KB).
## Operating
@@ -83,5 +102,7 @@ host advertises over mDNS as `_punktfunk._udp`, so clients discover it automatic
for a headless host.
- **WiFi tx ceiling** ≈ 250 Mbps goodput (a Deck hardware/driver packet-rate limit, band-independent);
fine for 1080p/1440p60. A wired dock lifts it.
- **After a major SteamOS update**, if the host won't start, run `update.sh` to rebuild against the new
base libraries.
- **After a SteamOS update** nothing should be needed: the `/etc` tuning survives via the
atomic-update keep list, and `punktfunk-rebuild-check` rebuilds the binary automatically if the
new base actually broke its library links (first session start after the update takes the build's
few minutes in that case). A manual `update.sh` remains harmless.