Skip to content

punktfunk-host

Recipe card from the charly-punktfunk plugin (Images — the deployable catalog).

punktfunk is a Rust game/desktop streaming host daemon: a native punktfunk/1 QUIC protocol plus Moonlight/GameStream compatibility. It is a different axis from the selkies-* / wayvnc / sway-* corpus, which streams a desktop out of a container over WebRTC/VNC — punktfunk is a host with its own protocol and a management plane.

Item Value
Packages punktfunk-host, punktfunk-web, punktfunk-scripting
Repo [punktfunk] in /etc/pacman.conf, SigLevel = Required DatabaseOptional
Key fetched + pacman-key --lsign-key’d; fingerprint E0CA04465C99C936E0B0C6510A317015A34DDD69
Ports udp:9777 (native QUIC), https+insecure:47990 (management API), https+insecure:47992 (web console)
Config ~/.config/punktfunk/host.env
Distros Arch and CachyOS — one distro.arch: section; the cachyos base declares distro: [cachyos, arch]

The Server line carries pacman’s own $repo / $arch variables. That is deliberate and works because the pac install template emits the line inside a single-quoted printf, so they reach pacman.conf verbatim for pacman to expand. Do not “fix” them into literals.

Two service forms, because punktfunk is a systemd USER service

Section titled “Two service forms, because punktfunk is a systemd USER service”

This is the single most important thing to understand before editing the candy.

  • systemd venue (VM / host deploy): the packaged punktfunk-host, punktfunk-web and punktfunk-scripting units are enabled with scope: user.
  • container venue: supervisord cannot use a systemd user unit, so the host runs through the candy’s own punktfunk-host-wrapper.

The wrapper waits for the Wayland socket and then sway’s IPC socket before exec’ing the host. That wait is load-bearing: punktfunk creates its virtual output by calling swaymsg create_output, so a host started before sway is listening runs but can never produce a display. It also sources host.env, which supervisord (unlike the packaged unit) does not read.

The wrapper mirrors pod-wayvnc’s wayvnc-wrapper deliberately — same dependency, same venue, one readiness idiom in the repo rather than two.

Lingering is part of installing it correctly

Section titled “Lingering is part of installing it correctly”

A scope: user unit only runs without an interactive login if the account lingers, and charly’s deploy path does not enable lingering on its own. The candy does it, capability-gated on /run/systemd/system so it no-ops during an image build and in a container, where there are no user units anyway.

PUNKTFUNK_COMPOSITOR=wlroots
PUNKTFUNK_INPUT_BACKEND=wlr
PUNKTFUNK_VIDEO_SOURCE=virtual
PUNKTFUNK_ENCODER=software
PUNKTFUNK_ZEROCOPY=0
PUNKTFUNK_MGMT_BIND=127.0.0.1:47990

Pinned rather than auto-detected on purpose: auto-detection picks whatever compositor is live, which would make a bed’s result depend on the venue instead of on the config. software + ZEROCOPY=0 is the only honest encoder path on a GPU-less bed; a GPU deploy overrides both in its own overlay. The host binds the management API to loopback — that is punktfunk’s own posture, and the punktfunk: verb probes from inside the venue rather than relaxing it.

Never setcap punktfunk-host. Upstream is explicit: capabilities belong on punktfunk-encode-worker, and setcap on the host breaks KDE desktop capture.

~/.config/punktfunk/mgmt-token is an env-file line, despite the docs implying otherwise:

PUNKTFUNK_MGMT_TOKEN=<64-hex-token>

Sending the whole line as a bearer yields a clean HTTP 401. /charly-check:punktfunk parses it.

Two, because one venue cannot prove both halves:

  • check-punktfunk-pod — the container venue (the wrapper launch path) and the only place the punktfunk: verb’s live dispatch is exercised.
  • check-punktfunk-vm — the systemd venue: the packaged user unit, lingering, and the management plane under a real init.

Both live in opencharly/distro-cachyos; run them with charly -C box/cachyos check run check-punktfunk-pod (or …-vm).