Follows the security audit (#5/#9): the GameStream-compat plane carries inherent on-path weaknesses that can't be fixed on the wire without breaking stock Moonlight — its pairing runs over plain HTTP (#9, MITM-able during the pairing window) and its legacy control encryption can reuse GCM nonces (#5, a passive eavesdropper can recover/forge input). The native punktfunk/1 plane (SPAKE2 PIN pairing + per-direction AEAD nonces) has neither. So flip the default to secure-by-default: - `serve` → native punktfunk/1 plane + management API ONLY (no GameStream surface). - `serve --gamestream` → ALSO the GameStream/Moonlight-compat planes (nvhttp pairing, RTSP, ENet control, _nvstream mDNS). Opt-in, logged with a trusted-LAN caveat. `--moonlight` is an alias. - The native plane is now ALWAYS on in `serve` (`--native` is a kept-for-compat no-op); the unified GameStream+native host is `serve --gamestream`. `gamestream::serve` gates the GameStream spawns (nvhttp/rtsp/control/mdns) on the flag; the native plane + mgmt + native-pairing handle always run. To avoid silently regressing validated Moonlight deployments, the explicit deployment configs PRESERVE Moonlight via `--gamestream` (each documents dropping it for a secure native-only host): the Linux systemd unit, the Steam Deck installer, and the Windows service default (DEFAULT_HOST_CMD). The bare `serve` default (new/manual use) is secure. Docs swept to match (host-cli, moonlight, quickstart, install, packaging READMEs, CLAUDE.md, README, …): Moonlight setup now instructs `--gamestream`; native/console refs use bare `serve`. OpenAPI regenerated (a stale "run `serve --native`" string). fmt + clippy clean; 94 host tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.2 KiB
title, description
| title | description |
|---|---|
| Ubuntu — KDE Plasma | Set up a punktfunk host on Ubuntu with KDE Plasma (KWin). |
Set up a punktfunk host on Ubuntu running KDE Plasma. The host uses KDE's KWin compositor to create a per-client virtual display. Needs KWin 6.5.6 or newer.
New to this? Skim Requirements first.
1. NVIDIA driver
Identical to the GNOME guide — follow step 1 of
Ubuntu — GNOME: install the NVIDIA driver and the
libnvidia-gl-<version> userspace, enable nvidia-drm modeset=1, reboot, and verify with
nvidia-smi.
2. Install the host (apt)
The host is published as a .deb to the public Gitea apt registry — install and update with plain
apt. Trust the repo's signing key, add the repo, and install:
sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://git.unom.io/api/packages/unom/debian/repository.key \
| sudo tee /etc/apt/keyrings/punktfunk.asc >/dev/null
echo "deb [signed-by=/etc/apt/keyrings/punktfunk.asc] https://git.unom.io/api/packages/unom/debian stable main" \
| sudo tee /etc/apt/sources.list.d/punktfunk.list
sudo apt update
sudo apt install punktfunk-host
This also pulls the web console (punktfunk-web) via Recommends (the pairing/status UI). The
desktop client — punktfunk-client, for the machine you stream to — is a separate package, not
needed on a host. The NVIDIA driver stays out of band (step 1). Updates later are just
sudo apt update && sudo apt upgrade.
3. Configure
The package ships the systemd user unit, the udev rule, and the sysctl tuning. As the desktop user, grant gamepad access and write the KDE config:
sudo usermod -aG input "$USER" # /dev/uinput for virtual gamepads (re-login to apply)
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
Make sure you're on a KDE Wayland session (not X11) — the picker on the login screen. The virtual-display path is Wayland-only. See the Configuration reference for every option.
4. Run
Start the host as a user service from inside your Plasma session:
systemctl --user enable --now punktfunk-host
journalctl --user -u punktfunk-host -f # watch it come up + print its fingerprint
The host listens on UDP 9777 (native punktfunk/1) plus the GameStream ports and advertises over
mDNS. It requires PIN pairing by default — arm pairing from the web console and pair once from
your client.
Web console
systemctl --user enable --now punktfunk-web
# read the auto-generated login password, then open http://<host-ip>:3000
journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p'
To run it at boot — including fully headless, with KWin brought up automatically and no login — see Running as a Service; the headless appliance is built around KDE.
Troubleshooting
- KWin too old: virtual outputs need KWin ≥ 6.5.6. Check with
kwin_wayland --version. - No picture / capture fails: confirm you're on a Wayland session and the NVIDIA GL userspace is
installed (
libnvidia-gl-<version>). More in Troubleshooting.
Appendix — build from source
If the apt registry has no build for your release, compile the host yourself (no clean updates / no
packaged units). Install the build toolchain and runtime libraries — the same apt line as the
GNOME build-from-source appendix — then:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
git clone https://git.unom.io/unom/punktfunk.git && cd punktfunk
cargo build --release -p punktfunk-host
Write ~/.config/punktfunk/host.env as in step 3, then run it inside your Plasma session:
cargo run --release -p punktfunk-host -- serve --gamestream
(The native plane is always on; --gamestream adds the Moonlight-compat surface this guide's
GameStream ports refer to — trusted LAN only. Drop it for a secure native-only host.)