From 59e91820ebeb737a86c646b3b47d2c5704bf6e1b Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sat, 13 Jun 2026 16:20:40 +0000 Subject: [PATCH] ci+docs: Fedora 44 RPM channel + reproducible Fedora KDE host guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docker.yml: build the punktfunk-fedora44-rpm builder image (parameterized Dockerfile, FEDORA_VERSION=44) alongside the F43/Bazzite one. - rpm.yml: matrix the build/publish over both channels — fedora-fedora-rpm→bazzite (F43, libavcodec.so.61) and fedora44-rpm→fedora-44 (F44, libavcodec.so.62). fail-fast:false so one channel's break doesn't sink the other. (Bootstrap: the F44 builder image must be pushed by docker.yml once before rpm.yml's fedora-44 job can pull it — same dance as the other images.) - fedora-kde.md: rewrite as the reproducible RPM-install guide validated live on a Fedora 44 KDE box (RTX 4090): RPM Fusion + akmod-nvidia + the ffmpeg-free→RPM-Fusion swap for NVENC + Secure Boot MOK enroll; the fedora-44 dnf repo + `dnf install punktfunk`; and the headless punktfunk-kde-session.service (kwin --virtual with NO_PERMISSION_CHECKS — an interactive Plasma session won't hand its privileged zkde_screencast protocol to an external client). Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/docker.yml | 7 +- .gitea/workflows/rpm.yml | 18 ++- docs-site/content/docs/fedora-kde.md | 158 ++++++++++++++++++--------- 3 files changed, 127 insertions(+), 56 deletions(-) diff --git a/.gitea/workflows/docker.yml b/.gitea/workflows/docker.yml index 45a116c..5bf0be3 100644 --- a/.gitea/workflows/docker.yml +++ b/.gitea/workflows/docker.yml @@ -42,6 +42,11 @@ jobs: - image: punktfunk-fedora-rpm dockerfile: ci/fedora-rpm.Dockerfile context: ci + # Fedora 44 builder (Fedora KDE spin): same Dockerfile, newer base → libavcodec.so.62. + - image: punktfunk-fedora44-rpm + dockerfile: ci/fedora-rpm.Dockerfile + context: ci + buildargs: --build-arg FEDORA_VERSION=44 steps: - uses: actions/checkout@v4 @@ -53,7 +58,7 @@ jobs: - name: Build run: | - docker build --pull \ + docker build --pull ${{ matrix.buildargs }} \ -f "${{ matrix.dockerfile }}" \ -t "$REGISTRY/$OWNER/${{ matrix.image }}:latest" \ -t "$REGISTRY/$OWNER/${{ matrix.image }}:sha-${GITHUB_SHA::8}" \ diff --git a/.gitea/workflows/rpm.yml b/.gitea/workflows/rpm.yml index 118af4d..02bd239 100644 --- a/.gitea/workflows/rpm.yml +++ b/.gitea/workflows/rpm.yml @@ -19,13 +19,23 @@ on: env: REGISTRY: git.unom.io OWNER: unom - RPM_GROUP: bazzite jobs: build-publish: runs-on: ubuntu-24.04 + # One RPM per target whose ffmpeg soname must match (a binary RPM is soname-coupled to its + # base): Fedora 43 == Bazzite (libavcodec.so.61), Fedora 44 == the Fedora KDE spin (.so.62). + # Each builds in its matching builder image and publishes to its own registry group. + strategy: + fail-fast: false + matrix: + include: + - image: punktfunk-fedora-rpm # Fedora 43 == Bazzite base + group: bazzite + - image: punktfunk-fedora44-rpm # Fedora 44 == Fedora KDE spin + group: fedora-44 container: - image: git.unom.io/unom/punktfunk-fedora-rpm:latest + image: git.unom.io/unom/${{ matrix.image }}:latest timeout-minutes: 90 env: CARGO_HOME: /usr/local/cargo @@ -72,6 +82,6 @@ jobs: case "$rpm" in *debuginfo*|*debugsource*) echo "skip $rpm"; continue;; esac echo "uploading $rpm" curl -fsS --user "enricobuehler:$TOKEN" --upload-file "$rpm" \ - "https://$REGISTRY/api/packages/$OWNER/rpm/$RPM_GROUP/upload" + "https://$REGISTRY/api/packages/$OWNER/rpm/${{ matrix.group }}/upload" done - echo "published to $OWNER/rpm/$RPM_GROUP" + echo "published to $OWNER/rpm/${{ matrix.group }}" diff --git a/docs-site/content/docs/fedora-kde.md b/docs-site/content/docs/fedora-kde.md index 0e43f27..23d6faf 100644 --- a/docs-site/content/docs/fedora-kde.md +++ b/docs-site/content/docs/fedora-kde.md @@ -1,18 +1,22 @@ --- title: Fedora — KDE Plasma -description: Set up a punktfunk host on Fedora with KDE Plasma (KWin). +description: Reproducible punktfunk host setup on Fedora KDE (KWin) via the RPM. --- -Set up a punktfunk host on **Fedora KDE** (the KDE Plasma spin). Like the Ubuntu KDE setup, the host -uses KWin to create per-client virtual displays — the difference is the package manager and the NVIDIA -driver source. +Set up a punktfunk host on **Fedora KDE** (the KDE Plasma spin). The host runs as an RPM-managed +systemd service and uses KWin to create per-client virtual displays, captured zero-copy +(dmabuf → CUDA → NVENC) on NVIDIA. -> Fedora KDE is the newest supported setup. The flow mirrors [Ubuntu — KDE](/docs/ubuntu-kde); this -> page covers the Fedora-specific bits. +> Validated live on **Fedora 44 KDE Plasma** with an RTX 4090: KWin virtual output + full +> zero-copy capture. Everything below is the reproducible flow — paste it on a fresh box. -## 1. NVIDIA driver +The setup has three parts: **NVIDIA driver** → **host RPM** → **KWin streaming session**. -The cleanest source on Fedora is **RPM Fusion**: +## 1. NVIDIA driver (RPM Fusion akmod) + +Enable RPM Fusion (free + nonfree), then install the akmod driver + CUDA. RPM Fusion's nonfree +NVIDIA repo is sometimes pre-enabled on the KDE spin; the full free/nonfree repos below are still +needed (they carry the NVENC ffmpeg in the next step). ```sh sudo dnf install \ @@ -21,60 +25,112 @@ sudo dnf install \ sudo dnf install akmod-nvidia xorg-x11-drv-nvidia-cuda ``` -Let the `akmod` build finish (a few minutes), then reboot. Verify: +**NVENC ffmpeg.** Fedora ships `ffmpeg-free`, which is built **without** NVENC — the host can't +encode with it. Swap to RPM Fusion's ffmpeg: ```sh -nvidia-smi -cat /sys/module/nvidia_drm/parameters/modeset # should print Y (RPM Fusion enables it by default) +sudo dnf install --allowerasing ffmpeg ffmpeg-libs +ffmpeg -hide_banner -encoders | grep nvenc # expect hevc_nvenc / av1_nvenc / h264_nvenc ``` -> With **Secure Boot** enabled, RPM Fusion's `akmods` need their key enrolled — follow the -> [RPM Fusion Secure Boot guide](https://rpmfusion.org/Howto/Secure%20Boot), or disable Secure Boot. +**Secure Boot.** If `mokutil --sb-state` says *enabled*, the akmod module is signed with a +locally-generated key that must be enrolled once: -## 2. Dependencies +```sh +sudo akmods --force # build + sign the module +sudo mokutil --import /etc/pki/akmods/certs/public_key.der # set a one-time password +sudo reboot +``` + +On the next boot a blue **MOK Manager** screen appears **on the machine's console** (not over +SSH): *Enroll MOK → Continue → Yes → (the password) → Reboot*. Then verify: + +```sh +nvidia-smi # driver loads +ffmpeg -hide_banner -encoders | grep nvenc +``` + +(Or disable Secure Boot in firmware to skip the MOK step — fine for a dedicated test box.) + +## 2. Install the host (RPM) + +The host is published to the self-hosted Gitea RPM registry, in a per-Fedora-release group (an RPM +is soname-coupled to its base, so Fedora 44 has its own `fedora-44` group). Add the repo and +install: + +```sh +sudo tee /etc/yum.repos.d/punktfunk.repo >/dev/null <<'REPO' +[punktfunk] +name=punktfunk +baseurl=https://git.unom.io/api/packages/unom/rpm/fedora-44 +enabled=1 +# Packages are unsigned; the repo METADATA is Gitea-signed — verify that, skip per-package sig. +gpgcheck=0 +repo_gpgcheck=1 +gpgkey=https://git.unom.io/api/packages/unom/rpm/repository.key +REPO + +sudo dnf install punktfunk +sudo usermod -aG input "$USER" # /dev/uinput access for virtual gamepads (re-login to apply) +``` + +Updates later are just `sudo dnf upgrade punktfunk`. The package ships the systemd user units, the +udev rule, the UDP socket-buffer sysctl tuning, and example configs. + +> No matching `fedora-NN` group for your release yet? Build one with the same toolchain CI uses — +> `docker build --build-arg FEDORA_VERSION=NN -f ci/fedora-rpm.Dockerfile -t pf-rpm ci` then run +> `packaging/rpm/build-rpm.sh` inside it — or build from source (appendix below). + +## 3. KWin streaming session + +KWin's virtual-output capture uses its **privileged** `zkde_screencast` protocol, which an +*interactive* Plasma session will not hand to an external client. So the host streams from a +**dedicated headless KWin session** (`kwin --virtual` launched with +`KWIN_WAYLAND_NO_PERMISSION_CHECKS=1`) — shipped as `punktfunk-kde-session.service`. This also +makes the box a self-contained appliance: it streams at boot with no graphical login. + +```sh +# KWin appliance config (ships with the package): +mkdir -p ~/.config/punktfunk +cp /usr/share/punktfunk/host.env.kde ~/.config/punktfunk/host.env + +# Start the headless KWin session + the host, and start user units at boot without a login: +systemctl --user daemon-reload +systemctl --user enable --now punktfunk-kde-session 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 +``` + +The host now listens on `9777` (native punktfunk/1) + the GameStream ports, and advertises over +mDNS. It requires **PIN pairing** by default (secure on a LAN); pair once from your client. + +## 4. Connect a client + +From any [client](/docs/clients) — `punktfunk-client --discover` finds the host on the LAN. On +first connect, complete the PIN pairing (arm it from the host's web console / mgmt API, or run the +host with `--allow-pairing`). See [Clients](/docs/clients) and +[Running as a Service](/docs/running-as-a-service). + +## Appendix — build from source + +If there's no RPM for your Fedora release and you don't want to build one, compile the host +directly (no clean updates / no packaged units — you wire those up by hand): ```sh sudo dnf install gcc gcc-c++ make cmake clang clang-devel nasm git \ - pipewire pipewire-pulseaudio wireplumber pipewire-devel \ - wayland-devel wayland-protocols-devel libxkbcommon-devel opus-devel \ + pipewire-devel wayland-devel wayland-protocols-devel libxkbcommon-devel opus-devel \ libdrm-devel mesa-libgbm-devel mesa-libEGL-devel mesa-libGLES-devel libva-devel \ - ffmpeg-free-devel libei-devel -``` - -> Fedora ships **FFmpeg** through RPM Fusion (`ffmpeg` + `ffmpeg-devel`) or the `-free` packages -> shown above. Either works; the host builds against the system FFmpeg. - -Install Rust: - -```sh + ffmpeg-devel libei-devel curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -``` - -## 3. Build - -```sh git clone https://git.unom.io/unom/punktfunk.git && cd punktfunk cargo build --release -p punktfunk-host ``` -## 4. Configure and run - -Same as Ubuntu KDE — write `~/.config/punktfunk/host.env` for KWin and run `serve --native`: - -```sh -mkdir -p ~/.config/punktfunk -cat > ~/.config/punktfunk/host.env <<'ENV' -WAYLAND_DISPLAY=wayland-0 -XDG_CURRENT_DESKTOP=KDE -PUNKTFUNK_COMPOSITOR=kwin -PUNKTFUNK_VIDEO_SOURCE=virtual -PUNKTFUNK_ZEROCOPY=1 -PUNKTFUNK_INPUT_BACKEND=libei -ENV - -cargo run --release -p punktfunk-host -- serve --native -``` - -Make sure you're on a **KDE Wayland** session with **KWin ≥ 6.5.6**. Then -[connect a client](/docs/clients). For boot-time startup, see -[Running as a Service](/docs/running-as-a-service). +Then write `~/.config/punktfunk/host.env` (as in `/usr/share/punktfunk/host.env.kde`, but the host +binary is `target/release/punktfunk-host`) and run it inside the KWin session from step 3.