Files
punktfunk/docs-site/content/docs/steamos-host.md
T
enricobuehler ba39b08e09
apple / swift (push) Successful in 1m6s
ci / rust (push) Successful in 5m51s
android / android (push) Successful in 6m21s
ci / web (push) Successful in 49s
ci / docs-site (push) Successful in 58s
windows-host / package (push) Successful in 8m6s
release / apple (push) Successful in 8m17s
deb / build-publish (push) Successful in 3m26s
decky / build-publish (push) Successful in 25s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
ci / bench (push) Successful in 4m42s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 30s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m36s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m17s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 19s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 51s
apple / screenshots (push) Successful in 5m45s
docker / deploy-docs (push) Successful in 22s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 22s
feat(web): consolidate paired devices, self-contained sections, docs + lint
Web console
- Pairing/Library/Stats refactored into self-contained subsections that each own
  their own queries + mutations; a shared slot-based layout (view.tsx) is filled by
  the live page (containers) and Storybook (pure cards + fixtures) so the layout can't
  drift.
- All paired devices in one list on Pairing with a protocol column (punktfunk/1 +
  Moonlight), routing each unpair to the right endpoint; the redundant Clients page is
  removed.
- Library: overview grid split from the add/edit form into separate files.
- Login screen links out to the docs.

Docs
- "Console login password" section on every host page (apt/RPM/Bazzite/SteamOS/Windows)
  plus a new "Forgot your Password?" troubleshooting page, linked from the login screen.
- Console served as HTTP/1.1 over TLS (drop the unusable HTTP/3 advertising) across the
  Bun entry, launchers, systemd units, and packaging.

Tooling
- Biome now respects .gitignore (stops linting generated code), config migrated to
  2.5.1; all lint issues fixed cleanly.

Also includes this branch's in-progress host, Apple client, packaging, and CI changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 19:05:22 +02:00

6.7 KiB
Raw Blame History

title, description
title description
SteamOS (Host) Run a punktfunk host on SteamOS — stream its Game Mode (or desktop) to your other devices. One script, built on-device and ABI-matched to SteamOS.

This is for using a SteamOS device as the host — streaming from it to a laptop, TV, phone, or another device. (For the usual case — streaming to a Steam Deck — see Install a Client, which uses the Flatpak + Decky plugin.)

We support SteamOS as a host mainly with an eye to the upcoming Steam Machine — a living-room, desktop-class SteamOS box is a natural always-on streaming host. The Steam Deck is the SteamOS device we can test on today, so it's what these instructions are validated against; the same on-device build works on any SteamOS 3 system.

SteamOS is an immutable, read-only Arch base, so the host isn't a system package. Instead a single script builds the host natively inside a Debian-trixie distrobox (ABI-matched to SteamOS's FFmpeg/glibc — the binary then runs natively on SteamOS) and wires it up as systemd user services. Building on-device means a rebuild always matches the running OS, so a SteamOS update can't leave you with a binary linked against the wrong libraries. Encode is VAAPI on the AMD GPU (auto-detected; NVENC on NVIDIA).

Heads up: in our testing the Steam Deck's WiFi tx topped out around ~250 Mbps of goodput regardless of band — enough for 1080p/1440p60, not 4K. This looked like a hardware/driver packet-rate limit rather than a bandwidth ceiling, but it's one device measured on one network: other SteamOS hardware, newer drivers, or a less congested band may do better. A wired dock sidesteps it entirely. See Configuration for bitrate guidance.

Prerequisites

  • A SteamOS device on SteamOS 3 (e.g. a Steam Deck, LCD or OLED). Steady WiFi or, better, a wired dock.
  • distrobox installed (no root needed). If distrobox isn't found:
    curl -sfL https://raw.githubusercontent.com/89luca89/distrobox/main/install | sh -s -- --prefix ~/.local
    
    Make sure ~/.local/bin is on your PATH (re-open the terminal).
  • The first build downloads a container image + toolchain (~1 GB) and takes ~1015 minutes. Later rebuilds are incremental.

1. Get the source

In Desktop Mode open Konsole (or ssh in), then:

git clone https://git.unom.io/unom/punktfunk ~/punktfunk

2. Run the installer

bash ~/punktfunk/scripts/steamdeck/install.sh

It is idempotent — safe to re-run. In one pass it:

  1. creates the pf2 Debian-trixie distrobox and installs the build toolchain,
  2. builds punktfunk-host (and the web console),
  3. writes config to ~/.config/punktfunk/ (a generated web-console login password),
  4. raises the UDP socket buffers to 32 MB and adds you to the input group (needs sudo; skipped with a warning if unavailable),
  5. installs + starts the punktfunk-host and punktfunk-web systemd user services (with linger, so they run without a login session).

Useful flags:

Flag Effect
--open Accept unpaired clients (trust-on-first-use) — convenient on a fully trusted LAN. Default is PIN pairing required.
--no-gamestream Run a secure native-only host — skip the GameStream/Moonlight-compat planes (see below). Default keeps them on so stock Moonlight works.
--no-web Skip the management web console.
--src=DIR Build from source at DIR instead of ~/punktfunk.

When it finishes it prints the web-console URL and how to pair.

GameStream/Moonlight compat is on by default. The native punktfunk/1 plane (used by punktfunk's own clients — SPAKE2 PIN pairing, per-direction AEAD) is always on and is the secure path. The installer also enables the GameStream/Moonlight-compat planes so stock Moonlight works — but those carry inherent on-path weaknesses (pairing over plain HTTP; legacy control encryption that can reuse GCM nonces), so enable them only on a trusted LAN. If you only ever use native clients, install with --no-gamestream for a host with no GameStream surface at all.

3. Pair a device

By default the host requires PIN pairing (secure). Two ways to pair:

  • Web console (printed at the end of step 2): open http://<device-ip>:3000, log in with the generated password (in ~/.config/punktfunk/web.env), go to Devices → arm pairing, and enter the PIN on your client.
  • From the client directly: pick this host (it advertises over mDNS as _punktfunk._udp) and enter the PIN the host shows.

On a trusted home LAN you can instead install with --open and skip pairing entirely.

Console login password

The installer generates a random console login password and writes it to ~/.config/punktfunk/web.env (as PUNKTFUNK_UI_PASSWORD=…); it's also printed at the end of the install run (step 2). Read it back with:

sed -n 's/^PUNKTFUNK_UI_PASSWORD=//p' ~/.config/punktfunk/web.env

To set your own password, edit that file and restart the console: systemctl --user restart punktfunk-web. Forgot it? This is the recovery path linked from the console login screen — see Forgot your Password?.

4. Verify

systemctl --user status punktfunk-host          # active (running)
journalctl --user -u punktfunk-host -f          # watch a client connect

Connect from a native client, or from Moonlight (unless you installed with --no-gamestream). In Game Mode the host attaches to the running gamescope session and streams it at your client's resolution; in Desktop Mode it streams the KDE desktop. The host auto-detects which session is live per connection.

Updating

After pulling new source, rebuild and restart in one step (config + pairings persist):

git -C ~/punktfunk pull          # or rsync new source in
bash ~/punktfunk/scripts/steamdeck/update.sh

Notes & limits

  • Single session at a time at custom resolutions — two clients requesting different modes will thrash the managed session. Pick one mode per session.
  • Keep the device awake. On handhelds, Game Mode auto-suspends on idle, which drops the host off the network mid stream — disable auto-suspend (Settings → Power) for a headless host.
  • It survives OS updates, but a major SteamOS bump can move library versions; if the host fails to start after an update, just re-run update.sh to rebuild against the new base.
  • Deeper reference (services, container, manual steps): scripts/steamdeck/README.md.

Trouble? See Troubleshooting and Pairing.