Field report (Nobara 43 HTPC): switching the host to Steam Game Mode mid-stream permanently black-screened the box. Live-proven root cause on a Nobara repro VM: our takeover masks the box's gamescope-session-plus unit, plasmalogin's Relogin=true then fails its session Exec repeatedly and trips systemd's start limit within ~1 s — the display manager dies, and our restore verb (unmask + user start) cannot bring a seatless gamescope back. Only 'reset-failed + restart' of the DM recovers. The takeover is now display-manager-flavor-aware: - SDDM (Bazzite/SteamOS) keeps the proven mask+SIGKILL path unchanged. - plasmalogin/unknown DMs never mask: with privilege (root or an operator polkit rule scoped to the DM unit — documented) the host stops the DM for the stream and restores it with reset-failed + restart (PUNKTFUNK_RECOVER_SESSION_CMD as fallback), recorded in the persisted takeover state so a host crash still restores; without privilege the managed takeover degrades to ATTACH and mirrors the box's live Game Mode instead of destabilizing the seat. Both legs of the privileged cycle live-verified on the repro VM (headless managed session works with zero login sessions; render nodes are 0666). A loaded-but-inactive leftover instance never triggers the DM stop. Companion fixes from the same triage: - ensure_box_gamescope_mode gains the attach-only rebuild-probe guard both managed paths already had (stale post-capture-loss detection restarted the box's unit), and no longer re-modes a box that drives a physical display — attach mirrors on-glass; re-mode is the headless-box model. - Capture-loss rebuilds targeting gamescope get a 100 s budget: the 40 s budget expired inside the first 45 s Steam-cold-start launch attempt, a guaranteed single-shot failure. - A PUNKTFUNK_COMPOSITOR pin now WARNs once per capture loss when the live session no longer matches it (the pin disables session-following — the reporter's original stream-death trigger). - A managed session that took nothing over (client gamescope pin beside a live desktop) is stopped on disconnect instead of being orphaned forever. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6.6 KiB
title, description
| title | description |
|---|---|
| Steam / gamescope | Configure a gamescope/Steam host — attach vs managed, session following, and limits. |
gamescope is the compositor behind Steam Gaming Mode — the couch/handheld game UI on Bazzite, SteamOS, or any distro running a gamescope session. The host auto-detects gamescope from your live session, so you rarely need to set anything here. It also follows a Gaming ↔ Desktop switch mid-stream — flip between Gaming Mode and the desktop with Steam's normal UI and the host re-targets whatever's running without a reconnect.
This page covers the gamescope-specific choices. To get a host running on an appliance box, start from the install guide for your OS: Bazzite or SteamOS (Host).
New here? Read Security & Safe Use first — a streaming host is remote control of the machine, so keep it on a trusted LAN or VPN and require pairing.
Attach vs managed
There are two mutually-exclusive models for a gamescope box; pick one. With nothing set, a box that has gamescope session infrastructure (Bazzite, SteamOS, Nobara) gets managed; the Bazzite template ships with attach chosen instead.
- Attach (
PUNKTFUNK_GAMESCOPE_ATTACH=1) — the box owns its gamescope session and decides Gaming vs Desktop via the normal Steam UI. Game Mode stays on the box's own (physical) display; the host 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. When the box is headless (no display connected) and the session is its own autologin unit, the host restarts it at the client's resolution on a mismatch; a box driving a physical display — and any foreign or bare gamescope — is streamed at its own mode. - Managed (the infra-detected default; force with
PUNKTFUNK_GAMESCOPE_MANAGED=1) — the host takes the box's gamescope session over and relaunches it headless at the client's exact resolution and refresh — Game Mode runs on the virtual screen, physical displays drop out of it — restoring the box on idle after disconnect.
Nobara and other autologin display managers
The managed takeover has to stop the box's Gaming Mode session to free Steam. How it does that depends on the display manager driving the autologin:
-
SDDM (Bazzite, SteamOS): handled automatically — no setup.
-
plasmalogin (Nobara) and other display managers: the host must stop the display manager itself for the length of the stream and restart it afterwards, which needs privilege. Allow it with a polkit rule (adjust the unit and user names to your box):
// /etc/polkit-1/rules.d/49-punktfunk-dm.rules polkit.addRule(function(action, subject) { if (action.id == "org.freedesktop.systemd1.manage-units" && action.lookup("unit") == "plasmalogin.service" && subject.user == "YOUR_USER") { return polkit.Result.YES; } });Without the rule the host degrades safely: it attaches to the live Gaming Mode session instead (Game Mode stays on the box's display, mirrored to the client) rather than risk the display manager. If the display-manager restart ever loses its privilege mid-restore,
PUNKTFUNK_RECOVER_SESSION_CMD(see Configuration) is fired as the fallback.
Session following
PUNKTFUNK_SESSION_WATCH follows a Gaming ↔ Desktop switch mid-stream — the host rebuilds the
backend in place, with no reconnect. It is on by default on Bazzite/SteamOS; set 0 to disable.
One host service covers both faces of the box: it streams Gaming Mode over gamescope and the desktop
over its own compositor, and re-targets whichever is live on each switch.
Start the host
On an appliance box (Bazzite, SteamOS) the install guide already enables the host service for you. On any other distro running a gamescope session, just start it — the host auto-detects the live gamescope session and picks the model for it:
systemctl --user enable --now punktfunk-host
Then bring up The Web Console to arm pairing.
gamescope knobs
The gamescope-specific settings in host.env. Leave them unset to auto-detect; set one only to force
a model. See the full Configuration reference for every other knob.
| Setting | Values | Meaning |
|---|---|---|
PUNKTFUNK_GAMESCOPE_ATTACH |
1 |
Attach model: the box owns its gamescope session (on its own display); the host captures whatever's live and never tears it down. On a headless box the box-owned autologin session is restarted at the client's resolution on a mismatch; a box driving a physical display, and any foreign/bare gamescope, streams at its own mode. |
PUNKTFUNK_GAMESCOPE_MANAGED |
1 |
Managed model (the default where session infra is detected): the host takes the box's gamescope over and relaunches it headless at the client's exact mode, restoring on idle. |
PUNKTFUNK_GAMESCOPE_SESSION |
steam |
The host owns a gamescope-session-plus (Steam) session at the client's mode — a headless appliance with no physical session running. |
PUNKTFUNK_GAMESCOPE_NODE |
auto · node id |
Discover and 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 in place, no reconnect). On by default on Bazzite/SteamOS; set 0 to disable. |
Known limits
These apply to the Gaming Mode (gamescope) path only; the desktop path is unaffected.
- gamescope 3.16.22 or newer is required. Older versions can deadlock during capture. Bazzite's and SteamOS'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.
- Touch arrives as a single-finger pointer. gamescope's virtual input device has no touchscreen, so the host maps a client's touchscreen to an absolute pointer: taps click exactly where you touch and drags work, but multi-touch gestures (pinch) aren't available in Gaming Mode. The desktop path has full multi-touch.
- HDR isn't supported on the gamescope path — gamescope's capture output is 8-bit. SDR streams normally.
To stream the KDE Plasma desktop of a Steam box instead, see KDE Plasma. To bring up the web console and pair a client, see The Web Console.