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

140 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "SteamOS (Host)"
description: "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](/docs/install-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](/docs/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:
```sh
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:
```sh
git clone https://git.unom.io/unom/punktfunk ~/punktfunk
```
## 2. Run the installer
```sh
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](/docs/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:
```sh
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?](/docs/forgot-password).
## 4. Verify
```sh
systemctl --user status punktfunk-host # active (running)
journalctl --user -u punktfunk-host -f # watch a client connect
```
Connect from a [native client](/docs/clients), or from [Moonlight](/docs/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):
```sh
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`](https://git.unom.io/unom/punktfunk/src/branch/main/scripts/steamdeck/README.md).
Trouble? See [Troubleshooting](/docs/troubleshooting) and [Pairing](/docs/pairing).