Files
punktfunk/packaging/debian
enricobuehler 8e18d01af5 fix(host/kwin): authorize Desktop-mode streaming via a shipped .desktop
Streaming the KDE *Desktop* (KWin) session failed on a real interactive
Plasma session with "KWin does not expose zkde_screencast_unstable_v1":
KWin treats the screencast/virtual-output and fake_input globals as
restricted and advertises them only to a client whose installed .desktop
lists them under X-KDE-Wayland-Interfaces (matched by /proc/<pid>/exe ->
Exec, and cached per-executable on first connect). The host shipped no
.desktop, so it was permanently denied; it only ever worked on the
headless dev box via KWIN_WAYLAND_NO_PERMISSION_CHECKS=1.

Ship packaging/linux/io.unom.Punktfunk.Host.desktop (least-privilege:
only the host, only zkde_screencast_unstable_v1 + org_kde_kwin_fake_input)
and install it from the RPM/.deb/Arch host packaging so it is present
before the host first connects. Drop the blunt session-wide
NO_PERMISSION_CHECKS hack from kde-desktop-setup.sh (it now only seeds the
RemoteDesktop input grant) and fix the now-misleading kwin.rs docs/errors.

Validated live on a Bazzite Kinoite box (KWin 6.6.4): probe-compositor +
spike --source kwin-virtual succeed against a KWin running WITHOUT the
permission bypass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 11:15:39 +00:00
..

punktfunk-host — Debian/Ubuntu package (apt)

punktfunk-host is published as a .deb to Gitea's Debian package registry in the public unom org, so the Ubuntu hosts update with plain apt. CI (.gitea/workflows/deb.yml) builds and publishes on every push to main (a rolling 0.3.0~ciN.g<sha> build to the canary apt distribution) and on vX.Y.Z tags (a clean X.Y.Z to the stable distribution, plus attached to the unified Gitea Release). The two are separate apt distributions, so a stable box never jumps to a canary build — see Release Channels. The repo line below subscribes to stable; swap stablecanary for the latest main builds.

The same workflow also publishes punktfunk-web (the browser management console — pairing + status) and punktfunk-client (the GTK4 couch/Deck client). punktfunk-host Recommends punktfunk-web, so a default apt install punktfunk-host pulls the console too (alongside the udev/sysctl bits) unless you've disabled weak deps; punktfunk-client is independent — install it on the box you stream to. (punktfunk-probe is the headless reference/test tool, not packaged here.)

Package layout mirrors the Fedora RPM (../rpm/punktfunk.spec): the host binary, the /dev/uinput udev rule, the systemd user unit, headless session helpers, the example config, and the OpenAPI doc. Runtime Depends are computed by dpkg-shlibdeps from the binary itself (built in the Ubuntu 26.04 rust-ci image, so the lib soname package names match the target). The NVIDIA driver (libnvidia-encode / libEGL_nvidia / libcuda) is not a dependency — it's installed out of band, like on the RPM side.

Install on a host (one-time)

The registry is public, so no apt auth is needed — just trust the repo's signing key:

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

Then, as the desktop user:

sudo usermod -aG input "$USER"          # virtual gamepads (re-login to take effect)
mkdir -p ~/.config/punktfunk
cp /usr/share/punktfunk-host/host.env.example ~/.config/punktfunk/host.env   # then edit
systemctl --user enable --now punktfunk-host
# Web console — enable it and read the auto-generated login password (then open http://<host-ip>:3000):
systemctl --user enable --now punktfunk-web
journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p'

Firewall

Open the ports the host listens on. The native punktfunk/1 plane:

  • QUIC control plane: UDP 9777 (serve --native-port N to change).
  • Data plane: an ephemeral UDP port — negotiated per session, so there is no fixed port to open. For a restrictive firewall you'd need to allow a UDP range (the repo does not pin one).

And the GameStream / Moonlight ports (fixed) — only needed if you run the host with serve --gamestream (opt-in, trusted LAN only); bare serve is native-only and doesn't open these:

Port Proto Purpose
47984 TCP HTTPS nvhttp (paired, mutual-TLS)
47989 TCP HTTP nvhttp (/serverinfo, /pair PIN flow)
48010 TCP RTSP handshake
4799848010 UDP Video RTP (+ FEC), ENet control (47999), audio (48000)
5353 UDP mDNS auto-discovery

The mgmt API (TCP 47990) binds to loopback by default — leave it closed unless you move it off loopback with --mgmt-bind IP:PORT (which then requires --mgmt-token).

With ufw:

sudo ufw allow 9777/udp                                 # punktfunk/1 control plane
sudo ufw allow 47984/tcp && sudo ufw allow 47989/tcp && sudo ufw allow 48010/tcp
sudo ufw allow 47998:48010/udp
sudo ufw allow 5353/udp
# plus the ephemeral punktfunk/1 data port — open a UDP range you reserve for it.

With raw nftables (add to your inet filter input chain):

udp dport 9777 accept                  # punktfunk/1 control plane
tcp dport { 47984, 47989, 48010 } accept
udp dport { 47998-48010, 5353 } accept
# plus the ephemeral punktfunk/1 data port (a reserved UDP range).

Updates

sudo apt update && sudo apt upgrade        # picks up the newest published build
systemctl --user restart punktfunk-host    # if the unit was already running

Build a .deb locally

VERSION=0.0.1 bash packaging/debian/build-deb.sh   # -> dist/punktfunk-host_0.0.1_amd64.deb

Needs dpkg-dev (dpkg-shlibdeps, dpkg-deb). It builds the release binary first if missing. Build it in the rust-ci image (or on an Ubuntu 26.04 box) so the resolved Depends match the hosts; building on a GPU box is fine — the NVIDIA driver lib is filtered out either way.