ci / web (push) Successful in 1m9s
ci / docs-site (push) Successful in 1m14s
ci / rust-arm64 (push) Successful in 3m28s
deb / build-publish-client-arm64 (push) Successful in 2m28s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 10s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 9s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 11s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 12s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 29s
android / android (push) Successful in 5m47s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m16s
docker / builders-arm64cross (push) Successful in 9s
deb / build-publish (push) Successful in 6m5s
docker / deploy-docs (push) Successful in 35s
deb / build-publish-host (push) Successful in 6m35s
ci / rust (push) Successful in 6m38s
arch / build-publish (push) Successful in 9m13s
apple / swift (push) Failing after 13m37s
apple / screenshots (push) Skipped
windows-host / package (push) Successful in 17m4s
windows-host / winget-source (push) Skipped
windows-host / canary-manifest (push) Successful in 20s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m17s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 39s
Field report (RX 5700 / SteamOS): 10-bit HEVC "unsupported" — but the GPU was
never the blocker (RADV probed Main10 fine on that box). The session stayed SDR
because stock gamescope offers no 10-bit PQ capture formats and nothing shipped
our pipewire-hdr build outside the Bazzite sysext, while PUNKTFUNK_GAMESCOPE_HDR
additionally defaulted off everywhere. Close all three gaps:
- PUNKTFUNK_GAMESCOPE_HDR now defaults ON (explicit-off grammar, the flip the
config comment planned post-canary). Safe by construction: the +pfhdr banner
probe, managed-spawn term, and client 10-bit cap keep stock-gamescope boxes on
the exact 8-bit path. The nix module's gamescopeHdr (default true now) only
controls whether the patched binary is on PATH; it no longer sets the env.
- SteamOS: new scripts/steamdeck/build-gamescope.sh builds the HDR gamescope in
the same pf2 trixie distrobox (apt dep list validated by a full build in a
debian:trixie container), installs ~/.local/bin/punktfunk-gamescope, and
maintains PUNKTFUNK_GAMESCOPE_BIN in host.env ONLY while the binary passes its
on-glass --version/+pfhdr check — a stale absolute override would break
session spawning, not just HDR. Wired into install.sh (§3b), update.sh
(retrofit), and rebuild-check.sh (ldd-probes it like the host binary).
- Arch: build-sysext.sh gains a --gamescope fold-in (banner-verified by
execution, host-image-only), and punktfunk-host optdepends the companion.
Deliberately NO CI-published host sysext: per the 2026-07-22 packaging
verdict a prebuilt SteamOS host breaks on A/B soname bumps (and /var is
per-partition-set), so arch.yml records that instead — SteamOS hosts use the
distrobox flow above.
Also fixes a latent bug that made build-sysext.sh fail every invocation as
documented: a literal `}` inside `${1:?usage …{host,client}…}` terminates the
expansion early and corrupts $PKG (caught by the new synthetic-package test,
which also covers the fold-in, the unmarked-gamescope refusal, and the
client-image guard).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
163 lines
7.8 KiB
Markdown
163 lines
7.8 KiB
Markdown
---
|
|
title: Arch Linux
|
|
description: Install a punktfunk host on Arch (and Arch-derived distros) from the signed pacman binary repo.
|
|
---
|
|
|
|
Set up a punktfunk host on **Arch Linux** (or an Arch-derived distro like CachyOS/EndeavourOS). The
|
|
host installs from a **signed pacman binary repo**, so it updates with `pacman -Syu` like the rest
|
|
of your system — no building required. Host encode is **NVENC on NVIDIA** and **VAAPI on
|
|
AMD/Intel** (`PUNKTFUNK_ENCODER=auto` picks per GPU).
|
|
|
|
> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of
|
|
> the machine, so keep it on a trusted LAN or VPN and require pairing.
|
|
|
|
> Prefer to build it yourself? A split `PKGBUILD` (host + client + optional web console) is in the
|
|
> repo at `packaging/arch/` — see the [appendix](#appendix--build-from-source-pkgbuild). The binary
|
|
> repo below is the supported path.
|
|
|
|
## 1. GPU prerequisites
|
|
|
|
- **NVIDIA:** `sudo pacman -S --needed nvidia-utils` (provides NVENC + the EGL/CUDA zero-copy path).
|
|
Arch's stock `ffmpeg` already has NVENC built in — no RPM-Fusion-style swap like Fedora needs.
|
|
- **AMD / Intel:** the Mesa stack (`mesa`, `libva-mesa-driver` for AMD, `intel-media-driver` for
|
|
Intel) provides the VAAPI encoder — usually already installed on a desktop.
|
|
|
|
## 2. Add the signed repo
|
|
|
|
The registry **signs its database and every package**, so first trust its key once (after this,
|
|
packages install signature-verified):
|
|
|
|
```sh
|
|
# Trust the registry signing key.
|
|
curl -fsS https://git.unom.io/api/packages/unom/arch/repository.key \
|
|
| sudo pacman-key --add -
|
|
sudo pacman-key --lsign-key E0CA04465C99C936E0B0C6510A317015A34DDD69
|
|
|
|
# Add the repo (append to /etc/pacman.conf). No SigLevel line needed — pacman's default
|
|
# verifies signed packages against the key you just trusted. (printf, not a heredoc, so this
|
|
# works in fish too — CachyOS's default shell has no `<<EOF` support.)
|
|
printf '\n[punktfunk]\nServer = https://git.unom.io/api/packages/unom/arch/$repo/$arch\n' \
|
|
| sudo tee -a /etc/pacman.conf >/dev/null
|
|
```
|
|
|
|
> **Stable vs canary.** `[punktfunk]` is the **stable** channel — it moves only when a `vX.Y.Z`
|
|
> release is cut. For the latest `main` build, use `[punktfunk-canary]` instead (same `Server` line,
|
|
> just the repo name). Enable exactly one. See [Release Channels](/docs/channels).
|
|
|
|
## 3. Install the host
|
|
|
|
```sh
|
|
sudo pacman -Sy punktfunk-host # the streaming host
|
|
sudo pacman -S punktfunk-web # optional: the browser management console (pairing + status)
|
|
sudo pacman -S punktfunk-gamescope # optional: HDR (10-bit BT.2020 PQ) off gamescope sessions
|
|
sudo usermod -aG input "$USER" # /dev/uinput access for virtual gamepads (re-login to apply)
|
|
```
|
|
|
|
`punktfunk-client` (the native GTK4 Linux client) is in the same repo if this box is also a client.
|
|
The host package ships the systemd **user** units, the udev rule, the UDP socket-buffer sysctl
|
|
tuning, and example configs. Updates later are just `sudo pacman -Syu`.
|
|
|
|
## 4. Configure and run
|
|
|
|
The host runs as a systemd **`--user`** service — it needs your session's PipeWire and D-Bus. Copy a
|
|
starting config:
|
|
|
|
```sh
|
|
mkdir -p ~/.config/punktfunk
|
|
cp /usr/share/punktfunk/host.env.example ~/.config/punktfunk/host.env
|
|
```
|
|
|
|
How the host creates its virtual display and injects input depends on your desktop, not your distro —
|
|
edit `host.env` for the desktop you run, following its page for the exact settings and any quirks:
|
|
|
|
- [KDE Plasma (KWin)](/docs/kde)
|
|
- [GNOME (Mutter)](/docs/gnome)
|
|
- [Steam / gamescope](/docs/gamescope)
|
|
- [Sway / wlroots](/docs/sway)
|
|
|
|
Then enable the service and turn on linger so it starts at boot without a login:
|
|
|
|
```sh
|
|
systemctl --user daemon-reload
|
|
systemctl --user enable --now punktfunk-host
|
|
sudo loginctl enable-linger "$USER"
|
|
```
|
|
|
|
Check it came up:
|
|
|
|
```sh
|
|
systemctl --user status punktfunk-host # active
|
|
journalctl --user -u punktfunk-host -f # watch a client connect
|
|
```
|
|
|
|
Enable the browser console, find your login password, and arm PIN pairing from
|
|
[The Web Console](/docs/web-console). For a headless KWin appliance that streams at boot with no
|
|
graphical login, see [KDE → Headless session](/docs/kde#headless-session). Full reference:
|
|
[Configuration](/docs/configuration) · [Running as a Service](/docs/running-as-a-service).
|
|
|
|
## 5. Open the firewall (if you have one)
|
|
|
|
**Stock Arch ships no firewall** — every port is already open, so you can skip this. But **CachyOS
|
|
enables `ufw` by default** (firewalld is not installed), and some other spins (e.g. EndeavourOS)
|
|
enable **`firewalld`** — an Arch package never opens ports for you, so on those the host is
|
|
unreachable until you allow it.
|
|
|
|
The `punktfunk-host` package installs openers for **both**, so it's a one-liner whichever you run:
|
|
|
|
```sh
|
|
# ufw — CachyOS (and Ubuntu, once you enable ufw):
|
|
sudo ufw allow punktfunk-native # the secure native host (the default)
|
|
sudo ufw allow punktfunk-gamestream # …also this if you run `serve --gamestream` (Moonlight)
|
|
|
|
# firewalld — Fedora-like spins (EndeavourOS, …):
|
|
sudo firewall-cmd --reload # load the installed definition
|
|
sudo firewall-cmd --permanent --add-service=punktfunk-native
|
|
sudo firewall-cmd --reload
|
|
```
|
|
|
|
`punktfunk-native` opens the QUIC control port (UDP 9777) + mDNS discovery; add
|
|
`punktfunk-gamestream` as well if you run `serve --gamestream` (the fixed Moonlight ports + mDNS).
|
|
The media **data plane** uses an *ephemeral* UDP port that the client opens with a hole-punch — the
|
|
host streams back out through the path the client opened, so there's **nothing fixed to open** as
|
|
long as the firewall allows outbound UDP (the default for both ufw and firewalld).
|
|
|
|
Enabled the **web console** (`punktfunk-web`, above) and want to reach it from your phone or another
|
|
machine? It's not opened by the streaming rules — open its port too, the same one-liner way:
|
|
|
|
```sh
|
|
sudo ufw allow punktfunk-web # ufw
|
|
sudo firewall-cmd --permanent --add-service=punktfunk-web && sudo firewall-cmd --reload # firewalld
|
|
```
|
|
|
|
That opens **TCP 47992** (HTTPS, login-gated). The mgmt API (47990) is opened for paired clients by the
|
|
`punktfunk-native` profile (game-library browsing over mTLS); off-loopback it serves only read-only
|
|
status/library, and every admin action stays loopback-only. Full port lists (`nftables`, explicit ports) are in
|
|
[`packaging/arch/README.md`](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/arch/README.md#firewall).
|
|
|
|
## 6. Connect a client
|
|
|
|
From any [client](/docs/clients), `--discover` finds the host on the LAN. On first connect, complete
|
|
the **PIN pairing**: arm it from [The Web Console](/docs/web-console#arm-pairing), which displays a
|
|
4-digit PIN to type into the client. (Pairing is required by default; pass `serve --open` only if
|
|
you deliberately want to disable it.) See [Clients](/docs/clients) for per-platform setup.
|
|
|
|
## Appendix — build from source (PKGBUILD)
|
|
|
|
To build instead of using the binary repo, use the split `PKGBUILD` in `packaging/arch/` (produces
|
|
`punktfunk-host` + `punktfunk-client`; set `PF_WITH_WEB=1` to also build `punktfunk-web`, which needs
|
|
`bun`):
|
|
|
|
```sh
|
|
git clone https://git.unom.io/unom/punktfunk.git && cd punktfunk/packaging/arch
|
|
# Build the working tree (no git fetch):
|
|
PF_SRCDIR="$(git rev-parse --show-toplevel)" makepkg -f --holdver
|
|
sudo pacman -U punktfunk-host-*.pkg.tar.zst
|
|
```
|
|
|
|
NVENC/EGL come from the NVIDIA driver (`nvidia-utils`); on a GPU-less builder, symlink the CUDA
|
|
stub into the link path first (the `PKGBUILD` header documents this). Full details, the
|
|
Fedora→Arch dependency map, and the systemd-sysext mechanism are in
|
|
[`packaging/arch/README.md`](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/arch/README.md).
|
|
(For a **SteamOS host**, use the [on-device installer](/docs/steamos-host) instead — it builds
|
|
the host and the HDR gamescope against the running OS.)
|