The shipped unit's PartOf=punktfunk-kde-session.service covers the APPLIANCE route, where we start the compositor ourselves. A host on a machine somebody logs into has no such unit: when Plasma or GNOME restarts, the daemon keeps running while holding a Wayland socket and a portal D-Bus connection that both died with the old compositor, and it cannot recover either in-process. It fails quietly — the host still listens, still answers, and every session it then serves dies at capture. A host that mirrors a monitor idles for days between sessions, which is the shape that finds this at the worst moment. The drop-in binds the host to graphical-session.target: PartOf takes it down with the session, WantedBy brings it back with the new one. Shipped under /usr/share rather than as an active drop-in, because it is wrong for the appliance route (which may never reach that target at all, and would then leave the host permanently stopped) — the operator opts in. Closes the restart half of design/per-monitor-portal-capture.md §6. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
55 lines
3.6 KiB
Desktop File
55 lines
3.6 KiB
Desktop File
# punktfunk streaming host — systemd USER unit (`serve --gamestream` = native punktfunk/1 + the
|
|
# GameStream/Moonlight-compat planes). For a SECURE native-only host (no plain-HTTP pairing / legacy
|
|
# GCM nonce reuse — security-review #5/#9; native clients only), drop `--gamestream` from ExecStart.
|
|
#
|
|
# Install (against an already-running compositor session — the host auto-detects and follows it,
|
|
# so host.env needs no backend config):
|
|
# mkdir -p ~/.config/systemd/user && cp scripts/punktfunk-host.service ~/.config/systemd/user/
|
|
# cp scripts/host.env.example ~/.config/punktfunk/host.env # defaults are right for a desktop
|
|
# systemctl --user daemon-reload && systemctl --user enable --now punktfunk-host
|
|
#
|
|
# On that desktop-login route, ALSO install scripts/punktfunk-host-desktop-session.conf as a drop-in:
|
|
# it binds the host to graphical-session.target, so a Plasma/GNOME restart restarts the host instead
|
|
# of leaving it holding a dead Wayland socket + portal connection (the PartOf= below only covers the
|
|
# appliance route, where we start the compositor ourselves). The drop-in's header has the commands.
|
|
#
|
|
# The host does NOT need the login shell's environment: it detects the live session itself per
|
|
# connect and derives WAYLAND_DISPLAY, XDG_RUNTIME_DIR, DBUS_SESSION_BUS_ADDRESS, XDG_CURRENT_DESKTOP,
|
|
# HYPRLAND_INSTANCE_SIGNATURE and SWAYSOCK from the running compositor (vdisplay::apply_session_env).
|
|
# So host.env carries policy, not session plumbing, and `systemctl --user import-environment` is not
|
|
# a prerequisite — the host pushes the live values into the manager env itself when a session switch
|
|
# needs the portal to re-read them.
|
|
#
|
|
# Self-contained boot appliance (no login, no manual steps after boot). These routes PIN the
|
|
# backend via PUNKTFUNK_COMPOSITOR — correct for a dedicated single-session box, but it turns off
|
|
# live-session auto-detection, so never do it on a desktop that switches sessions (Game Mode etc.):
|
|
# - kwin backend (stream the Plasma desktop): also install + enable
|
|
# punktfunk-kde-session.service (it brings up the headless KWin session this After=s), and use
|
|
# the shipped packaging/kde/host.env (pins kwin + WAYLAND_DISPLAY=wayland-kde on purpose).
|
|
# - gamescope backend (stream a nested app, no desktop): set PUNKTFUNK_COMPOSITOR=gamescope in
|
|
# host.env — the host spawns gamescope per session, so no kde-session unit is needed.
|
|
# Then `sudo loginctl enable-linger "$USER"` so user units start at boot, and reboot.
|
|
#
|
|
# The host LISTENS as soon as it starts and only touches the compositor per session (on a client
|
|
# connect), so the After= below is a soft ordering, not a hard readiness gate — the kde-session
|
|
# unit (when present) just needs to be up by the time a client streams (seconds later, user-driven).
|
|
# A missing After= unit (e.g. gamescope backend, no kde-session installed) is simply ignored.
|
|
[Unit]
|
|
Description=punktfunk GameStream + punktfunk/1 host
|
|
After=pipewire.service punktfunk-kde-session.service
|
|
# PartOf the kwin session (when present): the host's libei input uses the RemoteDesktop portal,
|
|
# whose D-Bus connection goes stale if the compositor session restarts the portal under it — the
|
|
# in-process reopen loop can't recover that, but a full restart re-establishes it. So restart the
|
|
# host whenever the kde-session restarts. Ignored when punktfunk-kde-session isn't installed
|
|
# (gamescope / other backends).
|
|
PartOf=punktfunk-kde-session.service
|
|
|
|
[Service]
|
|
EnvironmentFile=%h/.config/punktfunk/host.env
|
|
ExecStart=%h/punktfunk/target/release/punktfunk-host serve --gamestream
|
|
Restart=on-failure
|
|
RestartSec=2
|
|
|
|
[Install]
|
|
WantedBy=default.target
|