From dd4da9e04d99d7169322a9c9d3efc652f8d1bfd4 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Wed, 1 Jul 2026 20:06:28 +0000 Subject: [PATCH] docs: full env/config reference + fix outdated Bazzite gamescope-only framing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rebuild configuration.md into a complete PUNKTFUNK_* reference (verified against config.rs, the host.env templates, and the env read sites): core, gamescope/session-following, compositor, video quality, gamepads, audio, Windows host, auth/paths, perf tuning, diagnostics, and client-side knobs. Rework bazzite.md: it now documents both Steam Gaming Mode (gamescope) and the KDE Plasma desktop with auto-detect/session-following, attach vs managed, and the Desktop screencast + kde-desktop-setup.sh input grant — previously it only described the managed gamescope model. Co-Authored-By: Claude Opus 4.8 --- docs-site/content/docs/bazzite.md | 83 +++++++++--- docs-site/content/docs/configuration.md | 168 +++++++++++++++++++----- 2 files changed, 198 insertions(+), 53 deletions(-) diff --git a/docs-site/content/docs/bazzite.md b/docs-site/content/docs/bazzite.md index e8e8e63..b6ed6ad 100644 --- a/docs-site/content/docs/bazzite.md +++ b/docs-site/content/docs/bazzite.md @@ -1,15 +1,23 @@ --- -title: Bazzite — gamescope -description: Set up a punktfunk host on Bazzite, streaming a Steam/gamescope session at your client's mode. +title: Bazzite +description: Set up a punktfunk host on Bazzite — it follows the box between Steam Gaming Mode (gamescope) and the KDE Plasma desktop automatically. --- [Bazzite](https://bazzite.gg/) already ships everything a punktfunk host needs — the NVIDIA driver, -NVENC, PipeWire, and **gamescope**. So a Bazzite host is the most "appliance-like" setup: the host -launches its own gamescope session at the **client's** resolution and refresh, so your games run at -the mode of the device you're streaming to, not the TV the box is plugged into. +NVENC, PipeWire, **gamescope**, and the **KDE Plasma desktop**. So a Bazzite host is the most +"appliance-like" setup, and it streams **both** of Bazzite's faces: -> This is ideal for a dedicated game-streaming box. For a general desktop, prefer -> [Ubuntu/Fedora KDE](/docs/ubuntu-kde) or [GNOME](/docs/ubuntu-gnome). +- **Steam Gaming Mode** (gamescope) — the couch/handheld game UI. +- **The KDE Plasma desktop** — the full desktop you get from "Switch to Desktop". + +The host **auto-detects which one is live and follows the box across the switch** — including +mid-stream. You flip between Gaming Mode and Desktop with Bazzite's normal Steam UI / +"Switch to Desktop"; the host just re-targets whatever's running and keeps streaming. Nothing in +`host.env` forces a mode. + +> Ideal for a dedicated game-streaming box that you also occasionally want as a remote desktop. For a +> pure desktop machine, [Ubuntu/Fedora KDE](/docs/ubuntu-kde) or [GNOME](/docs/ubuntu-gnome) are +> simpler. ## Install @@ -58,31 +66,65 @@ permission, not a client problem.) ## Configure -The RPM ships a gamescope-ready config you can copy as your starting point: +The RPM ships a Bazzite-tuned config you can copy as your starting point: ```sh mkdir -p ~/.config/punktfunk cp /usr/share/punktfunk/host.env.bazzite ~/.config/punktfunk/host.env ``` -The key settings in `~/.config/punktfunk/host.env` point the host at the gamescope backend: +The template is deliberately minimal — it does **not** force a compositor, because the host +auto-detects Gaming Mode (gamescope) vs Desktop (KWin) on every connect and follows the switch +mid-stream. The only settings that matter are the session anchors plus zero-copy: ```sh -PUNKTFUNK_COMPOSITOR=gamescope -PUNKTFUNK_GAMESCOPE_SESSION=steam # the host owns a Steam session at the client's mode -PUNKTFUNK_INPUT_BACKEND=gamescope -PUNKTFUNK_ZEROCOPY=1 +XDG_RUNTIME_DIR=/run/user/1000 +DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus +PUNKTFUNK_VIDEO_SOURCE=virtual +PUNKTFUNK_ZEROCOPY=1 # GPU zero-copy (dmabuf → CUDA → NVENC); auto-falls back to CPU +PUNKTFUNK_GAMESCOPE_ATTACH=1 # Gaming Mode = attach to the box's own session (see below) ``` -With this, when a client connects the host starts a `gamescope-session-plus` (Steam) session at the -client's exact resolution and refresh, and relaunches it if the client changes mode. There should be -**no physical gaming session already running** on the box. +### Gaming Mode: attach vs managed + +For Gaming Mode there are two models (pick one; the shipped default is **attach**): + +- **Attach** (`PUNKTFUNK_GAMESCOPE_ATTACH=1`, the default) — the **box** owns its gamescope session + and decides Gaming vs Desktop via the normal Steam UI. The host just attaches to whatever's live + and never tears it down, so switching Desktop ↔ Game is rock-solid and disconnecting leaves the box + where it was. The streamed game-mode resolution is the box's gamescope mode + (`SCREEN_WIDTH/HEIGHT` in `/etc/gamescope-session-plus/sessions.d/steam`), not the client's. +- **Managed** (`PUNKTFUNK_GAMESCOPE_MANAGED=1`, and remove the attach line) — the host tears the + box's gamescope down on connect and launches its **own** at the *client's* exact resolution and + refresh, restoring on idle. Client-mode-following, but it can't coexist with a box-owned game-mode + session, and there must be **no physical gaming session already running**. + +Mid-stream Gaming ↔ Desktop following (`PUNKTFUNK_SESSION_WATCH`) is **on by default** on +Bazzite/SteamOS. See [Configuration](/docs/configuration) for the full list of knobs. + +### Streaming the KDE Plasma desktop + +The **virtual output** (video) for the Desktop session needs no config — the host package ships an +`io.unom.Punktfunk.Host.desktop` file whose `X-KDE-Wayland-Interfaces` grants the host KWin's +restricted screencast protocol on a normal interactive Plasma session (least-privilege, the same +mechanism krfb/krdp use). After a **fresh host install, log out and back into the Desktop session +once** so KWin re-reads that grant. + +The one thing a normal KDE login lacks is the RemoteDesktop grant for headless **input** injection. +Seed it once (as the streaming user, no root) so the host auto-approves instead of popping an +un-answerable dialog: + +```sh +bash /usr/share/punktfunk/bazzite/kde-desktop-setup.sh +``` + +Gaming Mode needs none of this — it auto-attaches. ## Run as an always-on host Bazzite hosts are typically headless. Enable the host service and linger so it starts at boot — see -[Running as a Service](/docs/running-as-a-service). Because the host launches its own gamescope -session per client, you don't need a separate desktop-session unit. +[Running as a Service](/docs/running-as-a-service). One host service covers both Gaming Mode and the +Desktop; it follows whichever the box is in. ```sh systemctl --user enable --now punktfunk-host @@ -109,9 +151,12 @@ the console login screen — see [Forgot your Password?](/docs/forgot-password). ## Good to know +These apply to the **Gaming Mode (gamescope)** path; the KDE Desktop path is unaffected: + - **gamescope 3.16.22 or newer is required.** Older versions can deadlock during capture. Bazzite's current gamescope is fine; this only bites if you've pinned an old one. -- **The mouse cursor isn't included in the captured image** — a gamescope limitation for now. +- **The mouse cursor isn't included in the captured image** — a gamescope limitation for now. (The + KDE Desktop path renders the cursor normally.) - **HDR isn't supported yet** on the gamescope path — gamescope's capture output is 8-bit. SDR streams normally. diff --git a/docs-site/content/docs/configuration.md b/docs-site/content/docs/configuration.md index c3dc186..7153993 100644 --- a/docs-site/content/docs/configuration.md +++ b/docs-site/content/docs/configuration.md @@ -1,63 +1,163 @@ --- title: Configuration -description: The host.env settings — compositor, resolution, bitrate, input — and how to tune them. +description: Every host.env setting and PUNKTFUNK_* environment variable — compositor, video, input, gamepads, tuning — and how to use them. --- -The host reads its settings from **`~/.config/punktfunk/host.env`** (a simple `KEY=value` file). Your +The host reads its settings from **`~/.config/punktfunk/host.env`** (a simple `KEY=value` file, `#` +starts a comment). On Windows the service reads **`%ProgramData%\punktfunk\host.env`** instead. Your [setup guide](/docs/requirements) gives you a starting `host.env` for your desktop; this page is the -reference. +full reference for every setting. -## Session settings +> **You rarely need most of these.** The host **auto-detects** the compositor, input backend, and +> encoder from your live session — a box that flips between Steam Gaming Mode and a KDE/GNOME desktop +> is followed automatically. The `PUNKTFUNK_*` knobs below are mostly **optional overrides** for +> forcing a specific backend, tuning performance, or debugging. The starter `host.env` for your +> platform sets only the few you actually need. -These tell the host which desktop session to attach to. Your setup guide sets them for you. +## Session anchors + +These tell the host which desktop session to attach to. Your setup guide sets them for you; they're +required when the host runs outside your interactive session (e.g. as a service). | Setting | What it does | |---|---| -| `WAYLAND_DISPLAY` | The Wayland socket of your session (`wayland-0` for a normal desktop). | +| `XDG_RUNTIME_DIR` | Your session's runtime dir (e.g. `/run/user/1000`). Always needed for a service. | +| `DBUS_SESSION_BUS_ADDRESS` | Your session bus (e.g. `unix:path=/run/user/1000/bus`). Always needed for a service. | +| `WAYLAND_DISPLAY` | The Wayland socket of your session (`wayland-0` for a normal desktop, `wayland-kde` for the headless-KDE unit). | | `XDG_CURRENT_DESKTOP` | Your desktop (`GNOME`, `KDE`). | -| `XDG_RUNTIME_DIR`, `DBUS_SESSION_BUS_ADDRESS` | Needed when the host runs outside your interactive session (e.g. as a service). | -## Core settings +On Linux the host **rewrites `WAYLAND_DISPLAY` / `XDG_CURRENT_DESKTOP` / `XDG_RUNTIME_DIR` / +`DBUS_SESSION_BUS_ADDRESS` on every connect** to follow the active session (Gaming ↔ Desktop). Only +`XDG_RUNTIME_DIR` and `DBUS_SESSION_BUS_ADDRESS` need to be pinned as trustworthy anchors. + +## Core | Setting | Values | Meaning | |---|---|---| -| `PUNKTFUNK_COMPOSITOR` | `mutter` · `kwin` · `gamescope` · `wlroots` | Which backend creates the virtual display. Match your desktop. | -| `PUNKTFUNK_VIDEO_SOURCE` | `virtual` · `portal` | `virtual` creates a per-client display at its exact mode (the normal choice). `portal` captures an existing monitor instead. | -| `PUNKTFUNK_ZEROCOPY` | `1` · `0` | GPU zero-copy capture→encode. Leave on; it falls back to a CPU path automatically. | -| `PUNKTFUNK_INPUT_BACKEND` | `libei` · `gamescope` · `wlr` · `uinput` | How input is injected. `libei` for GNOME/KDE, `gamescope` for Bazzite. | +| `PUNKTFUNK_COMPOSITOR` | `kwin` · `mutter` · `gamescope` · `wlroots` (aliases: `kde`/`plasma`, `gnome`, `sway`/`hyprland`) | Which backend creates the virtual display. **Leave unset to auto-detect;** set only to force one. | +| `PUNKTFUNK_VIDEO_SOURCE` | `virtual` · `portal` | `virtual` creates a per-client display at the client's exact mode (the normal choice). `portal` captures an existing monitor instead. | +| `PUNKTFUNK_ZEROCOPY` | `1` · `0` | GPU zero-copy capture→encode (dmabuf → CUDA → NVENC, or D3D11 on Windows). Leave on; it falls back to a CPU path automatically. | +| `PUNKTFUNK_INPUT_BACKEND` | `libei` · `gamescope` · `wlr` · `uinput` | How input is injected. `libei` for GNOME/KDE, `gamescope` for Bazzite/gamescope, `wlr` for Sway/wlroots. Auto-detected with the compositor. | +| `PUNKTFUNK_ENCODER` | `auto` · `nvenc` · `vaapi` (Linux) · `amf` · `qsv` · `sw` (Windows) | Encoder backend. `auto` (default) detects the GPU vendor: NVIDIA→NVENC, AMD→VAAPI/AMF, Intel→VAAPI/QSV, else software. | +| `PUNKTFUNK_RENDER_NODE` | path | Linux DRM render node for zero-copy (default `/dev/dri/renderD128`). Set on multi-GPU boxes to pick the right GPU. | -## Resolution and refresh rate +Resolution and refresh are **not** set here — **the client chooses them.** When a device connects, +the host creates a virtual display at that device's resolution and refresh rate. A 1080p60 laptop and +a 1440p120 desktop each get their own. (With Moonlight, set the mode in Moonlight; the native clients +let you pick a mode or default to the device's display.) -You don't set these on the host — **the client chooses them**. When a device connects, the host -creates a virtual display at that device's resolution and refresh rate. A 1080p60 laptop and a -1440p120 desktop each get their own. (With Moonlight, set the mode in Moonlight's settings; the -native clients let you pick a mode or default to the device's display.) +## gamescope / session following (Linux, Bazzite/SteamOS) + +Two mutually-exclusive models for a Steam/gamescope box. See [Bazzite](/docs/bazzite) for the full +picture. + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_GAMESCOPE_ATTACH` | `1` | **Attach** model: the box owns its gamescope session (you switch Gaming ↔ Desktop with the Steam UI); the host just captures whatever's live and never tears it down. Rock-solid; streamed resolution is the box's gamescope mode. | +| `PUNKTFUNK_GAMESCOPE_MANAGED` | `1` | **Managed** model: the host tears the box's gamescope down on connect and launches its **own** at the *client's* exact resolution, restoring on idle. Client-mode-following, but doesn't coexist with a box-owned game-mode session. | +| `PUNKTFUNK_GAMESCOPE_SESSION` | `steam` | The host owns a `gamescope-session-plus` (Steam) session at the client's mode (headless appliance; no physical session running). | +| `PUNKTFUNK_GAMESCOPE_NODE` | `auto` · node id | Discover + capture a **running** gamescope's PipeWire node at a fixed mode. Do **not** combine with `SESSION`. | +| `PUNKTFUNK_GAMESCOPE_APP` | command | For an ad-hoc bare-gamescope session, the nested command to run (e.g. `vkcube`). | +| `PUNKTFUNK_SESSION_WATCH` | `1` · `0` | Follow a Gaming ↔ Desktop switch **mid-stream** (rebuild the backend in place, no reconnect). **On by default** on Bazzite/SteamOS; set `0` to disable. | + +## Compositor-specific (Linux) + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_KWIN_VIRTUAL_PRIMARY` | `1` | Make the streamed per-session output the sole desktop so plasmashell + windows render on it (not on the headless bootstrap output). Set by the KDE appliance `host.env`. | +| `PUNKTFUNK_MUTTER_VIRTUAL_PRIMARY` | `1` | GNOME/Mutter equivalent of the above. | +| `PUNKTFUNK_MUTTER_VIRTUAL_REFRESH` | `1` | Pin the client's exact WxH**@Hz** via `RecordVirtual`'s custom modes (needed for >60 Hz on Mutter). | + +## Video quality + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_FEC_PCT` | `N` (percent) | Forward-error-correction redundancy for lossy links (the default is sensible for a normal LAN). Higher = more loss-resilient, more bandwidth. | +| `PUNKTFUNK_10BIT` | `1` | HEVC Main10 / HDR. Honored only when the client also advertises 10-bit. **Windows host only** (the Linux host stays 8-bit). | +| `PUNKTFUNK_444` | `1` | Full-chroma HEVC 4:4:4 (Range Extensions) — sharper text/desktop, no chroma loss. **punktfunk/1 native only** (Moonlight stays 4:2:0), HEVC-only, honored only when the client advertises 4:4:4 **and** the GPU supports it (probed; NVENC is the validated path — VAAPI/AMF/QSV decline). Independent of 10-bit. | +| `PUNKTFUNK_DSCP` | `1` | Opt-in DSCP / `SO_PRIORITY` QoS tagging on the media sockets. No-op on the wire on Windows without a qWAVE policy. | + +## Gamepads + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_GAMEPAD` | `xbox360` · `xboxone` · `dualsense` · `dualshock4` · `steamdeck` · `steamcontroller` (aliases: `ps5`, `ps4`, `deck`, …) | The virtual pad the host creates. Usually **auto-resolved from the client's physical controller** — set this only to force a type. `xbox360` (XInput) is the universal fallback. DualSense/DualShock 4/Steam Deck need Linux UHID; unsupported choices fold to Xbox 360. | +| `PUNKTFUNK_STEAM_GADGET` | `1` · `0` | Force the raw USB-gadget virtual Steam Deck on/off. **On by default on SteamOS**, off elsewhere. Lets Steam promote the virtual Deck to full Steam Input. | + +## Audio / microphone + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_AUDIO_GAIN` | float (default `1.0`) | Linear gain applied to capture — bump it for a quiet source. | +| `PUNKTFUNK_MIC_DEVICE` | name substring | **(Windows)** Target mic-uplink device by friendly-name substring (first match wins). | +| `PUNKTFUNK_NO_MIC_INSTALL` | set | **(Windows)** Skip installing the virtual-mic driver (e.g. when the host runs as SYSTEM). | + +## Windows host + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_VDISPLAY` | `pf` | Virtual-display backend. The bundled pf-vdisplay IddCx driver is the only backend now — informational; leave as `pf`. | +| `PUNKTFUNK_IDD_PUSH` | `1` · `0` | Capture straight from the pf-vdisplay driver's shared ring (the validated zero-copy path, incl. the secure desktop). Set `0` to force WGC/DDA capture. | +| `PUNKTFUNK_SECURE_DDA` | `1` | Capture the secure desktop (UAC / lock / login) so the stream survives those transitions. | +| `PUNKTFUNK_MONITOR_LINGER_MS` | ms (default `10000`) | Keep a per-client virtual display alive briefly after disconnect so a quick reconnect reuses it (no display connect/disconnect chime). | +| `PUNKTFUNK_RENDER_ADAPTER` | description substring | Multi-GPU boxes only: force the NVENC/capture GPU by adapter Description substring (e.g. `4090`). Leave unset on single-GPU machines. | +| `PUNKTFUNK_HOST_CMD` | e.g. `serve --gamestream` | The host subcommand the service launches. Default `serve --gamestream`; use `serve` for a secure native-only host. | + +## Auth, API & paths + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_MGMT_TOKEN` | token | Bearer token for the management API. If unset it's auto-generated and persisted to `~/.config/punktfunk/mgmt-token` (the bundled web console sources it). Set only to pin a specific token. | +| `PUNKTFUNK_UI_PASSWORD` | password | Web-console login password. Normally generated on first start and stored in `~/.config/punktfunk/web-password` — see [Forgot your Password?](/docs/forgot-password). | +| `PUNKTFUNK_CONFIG_DIR` | path | Override the config directory (default `~/.config/punktfunk`) — pairing state, certs, apps.json, captures. | + +## Advanced performance tuning + +Leave these at their defaults unless you're chasing latency; see the [troubleshooting](/docs/troubleshooting) +notes for context. + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_GSO` | `1` · `0` | UDP Generic Segmentation Offload on the send path (coalesce a frame's packets into kernel super-buffers) — the dominant lever above ~1 Gbps. On by default; auto-falls back to `sendmmsg`. Set `0` if a NIC/middlebox mishandles GSO. | +| `PUNKTFUNK_SPLIT_ENCODE` | `0`/`disable` · `1`/`auto` · `2` · `3` | NVENC N-way split-encode for very high pixel rates (5K@240). `auto` picks automatically above ~1 Gpix/s. | +| `PUNKTFUNK_GPU_PRIORITY_CLASS` | `off` · `normal` · `high` · `realtime` | **(Windows)** GPU scheduling priority for capture/encode under a GPU-saturating game. Default `high`; `realtime` is the strongest lever but can freeze NVENC on some setups. | +| `PUNKTFUNK_IDD_DEPTH` | `N` (default `2`) | **(Windows)** IDD-push pipeline depth. `1` cuts latency once GPU priority is raised; higher smooths a contended GPU. | + +## Diagnostics + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_PERF` | `1` | Log per-stage timing (capture, encode, send) — handy when tuning latency. | +| `RUST_LOG` | `info` · `debug` · `trace` | Log verbosity. On Windows, logs land in `%ProgramData%\punktfunk\logs\`. | +| `PUNKTFUNK_FFMPEG_DEBUG` | set | Verbose libavcodec/FFmpeg logging from the encoder. | +| `PUNKTFUNK_VIDEO_DROP` | `N` (percent) | Deliberately drop N% of video packets to exercise FEC recovery. **Testing only.** | + +## Client-side (native clients) + +A few knobs are read by the native **clients**, not the host: + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_DECODER` | `software` · `vaapi` (Linux) | Force the decode path. Default auto-selects hardware (VAAPI on Intel/AMD, D3D11VA on Windows) with a software fallback. | ## Bitrate -The client requests a bitrate; the host encodes to it. To find a good value for your link: +The client requests a bitrate; the host encodes to it. There's no host-side bitrate knob. To find a +good value: -- **Native clients (Apple, Linux, and more):** use the built-in **speed test** (from a host's menu). - It measures your link, suggests a bitrate, and applies it. +- **Native clients (Apple, Linux, Windows, Android):** use the built-in **speed test** (from a + host's menu). It measures your link, suggests a bitrate, and applies it. - **Moonlight:** set the bitrate in Moonlight's settings. Start moderate and raise it. ## Multiple devices at once -Today the native `punktfunk/1` host (`serve`) streams **one session at a time** — additional -clients wait in the accept queue until the active session ends. Each session gets its own virtual -display at the client's exact resolution; concurrent native sessions are on the roadmap. - -(`punktfunk1-host`, the standalone test host, has a `--max-concurrent N` knob, default 4, bounded by your -GPU's encoder — see the [Host CLI](/docs/host-cli) reference — but `serve` does **not** take -that flag.) +Today the native `punktfunk/1` host (`serve`) streams **one session at a time** — additional clients +wait in the accept queue until the active session ends. Each session gets its own virtual display at +the client's exact resolution; concurrent native sessions are on the roadmap. (`punktfunk1-host`, the +standalone test host, has a `--max-concurrent N` knob — see the [Host CLI](/docs/host-cli) reference — +but `serve` does not take that flag.) ## Codec and FEC - The host encodes **HEVC (H.265)** by default; **AV1** is available for clients that support it. -- The native protocol adds forward error correction for lossy links. `PUNKTFUNK_FEC_PCT=N` sets the - redundancy percentage (the default is sensible for a normal LAN). - -## Diagnostics - -- `PUNKTFUNK_PERF=1` logs per-stage timing (capture, encode, send) — handy when tuning latency. -- `RUST_LOG=info` (or `debug`) controls log verbosity. +- The native protocol adds forward error correction for lossy links — see `PUNKTFUNK_FEC_PCT` above.