From 69fcb6e0b11b739fb28f942780ccddeea5f212a2 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 5 Jul 2026 21:04:31 +0000 Subject: [PATCH] docs: restructure host setup by distro, configuration by compositor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the docs' single distro×desktop axis (ubuntu-gnome / ubuntu-kde / fedora-kde) into two, which deduplicates the shared mechanics and scales to distros that run several desktops (Arch): - Install the host — per distro/OS (ubuntu, fedora, arch, bazzite, steamos-host, windows-host): GPU driver + package + input group, then a canonical "Configure your desktop" funnel. - Configure your desktop — per compositor (kde, gnome, gamescope, sway): host.env, compositor quirks, the headless session, and starting the host. New shared web-console page (enable · login password · arm pairing) removes the console/password block that was copy-pasted across all seven host pages. Merged ubuntu-gnome + ubuntu-kde into ubuntu; renamed fedora-kde to fedora; kept bazzite and steamos-host as dedicated appliance guides (trimmed of duplication). Moved the KWin headless session, the GNOME EGL/lock traps, and the gamescope attach/managed model out of the distro pages onto their compositor pages. Fixed while restructuring: distro-specific paths on kde (kde-desktop-setup.sh is Fedora/Bazzite-only; the .deb ships host.env.kde under /usr/share/punktfunk-host), the interactive "start the host" step that was lost in the merge, sway over-claiming Hyprland, and a pre-existing broken anchor in how-it-works. Removal of the three old pages was captured by the preceding commit 8ebb614 (a concurrent commit swept up the staged git-rm); the net docs tree is correct. Fumadocs build + internal link/anchor check green. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs-site/content/docs/arch.md | 58 +++----- docs-site/content/docs/bazzite.md | 50 +++---- docs-site/content/docs/configuration.md | 6 +- docs-site/content/docs/fedora.md | 138 ++++++++++++++++++ docs-site/content/docs/forgot-password.md | 13 +- docs-site/content/docs/gamescope.md | 77 ++++++++++ docs-site/content/docs/gnome.md | 96 ++++++++++++ docs-site/content/docs/how-it-works.md | 2 +- docs-site/content/docs/index.mdx | 4 +- docs-site/content/docs/install.md | 17 ++- docs-site/content/docs/kde.md | 113 ++++++++++++++ docs-site/content/docs/meta.json | 22 +-- docs-site/content/docs/quickstart.md | 24 +-- docs-site/content/docs/requirements.md | 48 +++--- .../content/docs/running-as-a-service.md | 47 ++---- docs-site/content/docs/steamos-host.md | 22 +-- docs-site/content/docs/sway.md | 68 +++++++++ docs-site/content/docs/troubleshooting.md | 12 +- docs-site/content/docs/ubuntu.md | 133 +++++++++++++++++ docs-site/content/docs/web-console.md | 73 +++++++++ docs-site/content/docs/windows-host.md | 23 ++- 21 files changed, 854 insertions(+), 192 deletions(-) create mode 100644 docs-site/content/docs/fedora.md create mode 100644 docs-site/content/docs/gamescope.md create mode 100644 docs-site/content/docs/gnome.md create mode 100644 docs-site/content/docs/kde.md create mode 100644 docs-site/content/docs/sway.md create mode 100644 docs-site/content/docs/ubuntu.md create mode 100644 docs-site/content/docs/web-console.md diff --git a/docs-site/content/docs/arch.md b/docs-site/content/docs/arch.md index a8a0497..193859b 100644 --- a/docs-site/content/docs/arch.md +++ b/docs-site/content/docs/arch.md @@ -58,25 +58,30 @@ tuning, and example configs. Updates later are just `sudo pacman -Syu`. ## 4. Configure and run -The host runs as a systemd **`--user`** service — it needs your session's PipeWire and D-Bus. -Copy a starting config, enable the service, and enable linger so it starts at boot without a login: +The host runs as a systemd **`--user`** service — it needs your session's PipeWire and D-Bus. Copy a +starting config: ```sh mkdir -p ~/.config/punktfunk -cp /usr/share/punktfunk/host.env.example ~/.config/punktfunk/host.env # then edit +cp /usr/share/punktfunk/host.env.example ~/.config/punktfunk/host.env +``` + +How the host creates its virtual display and injects input depends on your desktop, not your distro — +edit `host.env` for the desktop you run, following its page for the exact settings and any quirks: + +- [KDE Plasma (KWin)](/docs/kde) +- [GNOME (Mutter)](/docs/gnome) +- [Steam / gamescope](/docs/gamescope) +- [Sway / wlroots](/docs/sway) + +Then enable the service and turn on linger so it starts at boot without a login: + +```sh systemctl --user daemon-reload systemctl --user enable --now punktfunk-host sudo loginctl enable-linger "$USER" ``` -Which compositor the host captures depends on your desktop — it drives a per-client virtual output -via KWin (Plasma), Mutter (GNOME), or wlroots (Sway), or spawns a headless **gamescope** session -per connect. For a headless appliance, the package also ships `punktfunk-kde-session.service` -(a dedicated `kwin --virtual` session, same as the [Fedora KDE](/docs/fedora-kde#3-kwin-streaming-session) -guide — `cp /usr/share/punktfunk/host.env.kde ~/.config/punktfunk/host.env` and enable it alongside -the host). See [Configuration](/docs/configuration) for every knob and -[Running as a Service](/docs/running-as-a-service) for the service model. - Check it came up: ```sh @@ -84,27 +89,10 @@ systemctl --user status punktfunk-host # active journalctl --user -u punktfunk-host -f # watch a client connect ``` -### Web console - -The console (status, paired devices, arm pairing) ships as `punktfunk-web` — enable it, then open -`http://:47992`: - -```sh -systemctl --user enable --now punktfunk-web -``` - -#### Console login password - -On first start `punktfunk-web-init` generates a random login password and saves it to -`~/.config/punktfunk/web-password` (as `PUNKTFUNK_UI_PASSWORD=…`). Read it back at any time: - -```sh -journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p' -sed -n 's/^PUNKTFUNK_UI_PASSWORD=//p' ~/.config/punktfunk/web-password -``` - -To set your own, edit that file and `systemctl --user restart punktfunk-web`. Forgot it? See -[Forgot your Password?](/docs/forgot-password). +Enable the browser console, find your login password, and arm PIN pairing from +[The Web Console](/docs/web-console). For a headless KWin appliance that streams at boot with no +graphical login, see [KDE → Headless session](/docs/kde#headless-session). Full reference: +[Configuration](/docs/configuration) · [Running as a Service](/docs/running-as-a-service). ## 5. Open the firewall (if you have one) @@ -147,9 +135,9 @@ opened. Full port lists (`nftables`, explicit ports) are in ## 6. Connect a client From any [client](/docs/clients), `--discover` finds the host on the LAN. On first connect, complete -the **PIN pairing** — arm it from the host's web console, which displays a 4-digit PIN to type into -the client. (Pairing is required by default; pass `serve --open` only if you deliberately want to -disable it.) See [Clients](/docs/clients) and [Pairing](/docs/pairing). +the **PIN pairing**: arm it from [The Web Console](/docs/web-console#arm-pairing), which displays a +4-digit PIN to type into the client. (Pairing is required by default; pass `serve --open` only if +you deliberately want to disable it.) See [Clients](/docs/clients) for per-platform setup. ## Appendix — build from source (PKGBUILD) diff --git a/docs-site/content/docs/bazzite.md b/docs-site/content/docs/bazzite.md index 7e28ce2..1ac2d47 100644 --- a/docs-site/content/docs/bazzite.md +++ b/docs-site/content/docs/bazzite.md @@ -16,8 +16,8 @@ mid-stream. You flip between Gaming Mode and Desktop with Bazzite's normal Steam `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. +> pure desktop machine, install on [Ubuntu](/docs/ubuntu) or [Fedora](/docs/fedora) and configure the +> [KDE](/docs/kde) or [GNOME](/docs/gnome) desktop directly — simpler. > New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of > the machine, so keep it on a trusted LAN or VPN and require pairing. @@ -60,7 +60,7 @@ For a fully baked appliance image there's also a **bootc** Containerfile that in from the registry at image-build time — see `packaging/bootc/` in the repo. Plain `rpm-ostree` layering from the [RPM registry](https://git.unom.io/unom/-/packages) keeps working too (see `packaging/bazzite/README.md`), but the sysext is the supported default. Building from source -also works (Bazzite is Fedora Atomic underneath — same steps as [Fedora KDE](/docs/fedora-kde)). +also works (Bazzite is Fedora Atomic underneath — same steps as [Fedora](/docs/fedora)). ## Allow controller input @@ -99,15 +99,14 @@ PUNKTFUNK_GAMESCOPE_ATTACH=1 # Gaming Mode = attach to the box's own session 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**. +- **Attach** (`PUNKTFUNK_GAMESCOPE_ATTACH=1`, the default) — the **box** owns its gamescope session, + the host attaches to whatever's live and never tears it down, and the streamed game-mode resolution + is the box's own gamescope mode. Switching Desktop ↔ Game is rock-solid. +- **Managed** (`PUNKTFUNK_GAMESCOPE_MANAGED=1`, and remove the attach line) — the host launches its + **own** gamescope at the *client's* exact resolution and refresh. Client-mode-following, but there + must be no physical gaming session already running. + +Full treatment: [Steam / gamescope → Attach vs managed](/docs/gamescope#attach-vs-managed). 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. @@ -116,8 +115,8 @@ Bazzite/SteamOS. See [Configuration](/docs/configuration) for the full list of k 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 +restricted screencast protocol on a normal interactive Plasma session (background: +[KDE Plasma](/docs/kde)). 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. @@ -138,26 +137,11 @@ Desktop; it follows whichever the box is in. ```sh systemctl --user enable --now punktfunk-host -# Web console (pairing + status) — enable it and read the auto-generated login password, -# then open http://:47992: -systemctl --user enable --now punktfunk-web -journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p' +systemctl --user enable --now punktfunk-web # web console: pairing + status ``` -### Console login password - -The console is password-protected. On first start `punktfunk-web-init` generates a random login -password and saves it to `~/.config/punktfunk/web-password` (as `PUNKTFUNK_UI_PASSWORD=…`). Read it -back at any time — from the init service's journal, or straight from the file: - -```sh -journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p' -sed -n 's/^PUNKTFUNK_UI_PASSWORD=//p' ~/.config/punktfunk/web-password -``` - -To set your own password, edit that file (`PUNKTFUNK_UI_PASSWORD=`) 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). +Then open [The Web Console](/docs/web-console) for the login password and to +[arm pairing](/docs/web-console#arm-pairing). ## Good to know @@ -170,5 +154,7 @@ These apply to the **Gaming Mode (gamescope)** path; the KDE Desktop path is una - **HDR isn't supported yet** on the gamescope path — gamescope's capture output is 8-bit. SDR streams normally. +Canonical list: [gamescope → Known limits](/docs/gamescope#known-limits). + Then [connect a client](/docs/clients) — Moonlight works great for couch gaming, and the Apple app for Apple TV / iPad. diff --git a/docs-site/content/docs/configuration.md b/docs-site/content/docs/configuration.md index c991f6d..c92cb64 100644 --- a/docs-site/content/docs/configuration.md +++ b/docs-site/content/docs/configuration.md @@ -48,8 +48,8 @@ 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. +Two mutually-exclusive models for a Steam/gamescope box. See [Steam / gamescope](/docs/gamescope) for +the full picture (and [Bazzite](/docs/bazzite) for that distro's specifics). | Setting | Values | Meaning | |---|---|---| @@ -62,6 +62,8 @@ picture. ## Compositor-specific (Linux) +See your desktop page ([KDE](/docs/kde), [GNOME](/docs/gnome)) for when to set these. + > **Managing virtual displays** — keep-alive after disconnect, exclusive vs. extend, and (on > Windows/KDE) persistent per-client scaling — now has its own settings surface in the web console > and `display-settings.json`. See [Virtual displays](/docs/virtual-displays). The two diff --git a/docs-site/content/docs/fedora.md b/docs-site/content/docs/fedora.md new file mode 100644 index 0000000..80ece2d --- /dev/null +++ b/docs-site/content/docs/fedora.md @@ -0,0 +1,138 @@ +--- +title: Fedora +description: Install the punktfunk host on Fedora from the RPM registry. +--- + +Install a punktfunk host on **Fedora** from the self-hosted RPM registry. The host installs as an +RPM-managed systemd **`--user`** service and updates with `dnf upgrade` like the rest of your +system — no building required. It works with either **KDE Plasma** or **GNOME**; the +desktop-specific setup (which compositor captures, headless sessions, quirks) lives on the +[desktop configure pages](#3-configure-your-desktop). Host encode is **NVENC on NVIDIA** and **VAAPI on +AMD/Intel** (`PUNKTFUNK_ENCODER=auto` picks per GPU). + +> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of +> the machine, so keep it on a trusted LAN or VPN and require pairing. + +Install is two parts: **GPU driver** → **host RPM**. Then point the host at your desktop from the +[desktop configure pages](#3-configure-your-desktop). + +## 1. NVIDIA driver (RPM Fusion akmod) + +Enable RPM Fusion (free + nonfree), then install the akmod driver + CUDA. RPM Fusion's nonfree +NVIDIA repo is sometimes pre-enabled on some spins; the full free/nonfree repos below are still +needed (they carry the NVENC ffmpeg in the next step). + +```sh +sudo dnf install \ + https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm \ + https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm +sudo dnf install akmod-nvidia xorg-x11-drv-nvidia-cuda +``` + +**NVENC ffmpeg.** Fedora ships `ffmpeg-free`, which is built **without** NVENC — the host can't +encode with it. Swap to RPM Fusion's ffmpeg: + +```sh +sudo dnf install --allowerasing ffmpeg ffmpeg-libs +ffmpeg -hide_banner -encoders | grep nvenc # expect hevc_nvenc / av1_nvenc / h264_nvenc +``` + +**Secure Boot.** If `mokutil --sb-state` says *enabled*, the akmod module is signed with a +locally-generated key that must be enrolled once: + +```sh +sudo akmods --force # build + sign the module +sudo mokutil --import /etc/pki/akmods/certs/public_key.der # set a one-time password +sudo reboot +``` + +On the next boot a blue **MOK Manager** screen appears **on the machine's console** (not over +SSH): *Enroll MOK → Continue → Yes → (the password) → Reboot*. Then verify: + +```sh +nvidia-smi # driver loads +ffmpeg -hide_banner -encoders | grep nvenc +``` + +(Or disable Secure Boot in firmware to skip the MOK step — fine for a dedicated test box.) + +**AMD / Intel (VAAPI).** No akmod needed — the Mesa stack provides the VAAPI encoder. Install the +freeworld VAAPI drivers for full codec support (`mesa-va-drivers-freeworld` for AMD from RPM Fusion, +`intel-media-driver` for Intel); on a desktop these are usually already present. The host auto-picks +VAAPI on these GPUs. + +## 2. Install the host (RPM) + +The host is published to the self-hosted Gitea RPM registry, in a per-Fedora-release group (an RPM +is soname-coupled to its base, so Fedora 44 has its own `fedora-44` group). Add the repo and +install: + +```sh +sudo tee /etc/yum.repos.d/punktfunk.repo >/dev/null <<'REPO' +[punktfunk] +name=punktfunk +baseurl=https://git.unom.io/api/packages/unom/rpm/fedora-44 +enabled=1 +# Packages are GPG-signed (gpgcheck=1) AND the repo metadata is Gitea-signed (repo_gpgcheck=1). +gpgcheck=1 +repo_gpgcheck=1 +gpgkey=https://git.unom.io/api/packages/unom/rpm/repository.key + https://git.unom.io/api/packages/unom/generic/punktfunk-keys/1/RPM-GPG-KEY-punktfunk +REPO + +sudo dnf install punktfunk +sudo usermod -aG input "$USER" # /dev/uinput access for virtual gamepads (re-login to apply) +``` + +Updates later are just `sudo dnf upgrade punktfunk`. The package ships the systemd user units, the +udev rule, the UDP socket-buffer sysctl tuning, and example configs. + +> No matching `fedora-NN` group for your release yet? Build one with the same toolchain CI uses — +> `docker build --build-arg FEDORA_VERSION=NN -f ci/fedora-rpm.Dockerfile -t pf-rpm ci` then run +> `packaging/rpm/build-rpm.sh` inside it — or build from source (appendix below). + +## 3. Configure your desktop + +How the host creates its virtual display and injects input depends on your desktop, not your distro. +Continue on the page for the desktop you run — it covers your `host.env`, any compositor quirks, and +starting the host: + +- [KDE Plasma (KWin)](/docs/kde) +- [GNOME (Mutter)](/docs/gnome) +- [Steam / gamescope](/docs/gamescope) +- [Sway / wlroots](/docs/sway) + +Enable the browser management console (status, paired devices, arm pairing) — see +[Web Console](/docs/web-console). + +For a headless KWin appliance that streams at boot with no graphical login, see +[KDE → Headless session](/docs/kde#headless-session). + +Full config reference: [Configuration](/docs/configuration). Service model: +[Running as a Service](/docs/running-as-a-service). + +## 4. Connect a client + +From any [client](/docs/clients), `--discover` finds the host on the LAN. On first connect, complete +the **PIN pairing** — arm it from the host's [web console](/docs/web-console#arm-pairing), which +displays a 4-digit PIN to type into the client. See [Clients](/docs/clients) and +[Pairing](/docs/pairing). + +## Appendix — build from source + +If there's no RPM for your Fedora release and you don't want to build one, compile the host directly +(no clean updates / no packaged units — you wire those up by hand): + +```sh +sudo dnf install gcc gcc-c++ make cmake clang clang-devel nasm git \ + pipewire-devel wayland-devel wayland-protocols-devel libxkbcommon-devel opus-devel \ + libdrm-devel mesa-libgbm-devel mesa-libEGL-devel mesa-libGLES-devel libva-devel \ + ffmpeg-devel libei-devel +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +git clone https://git.unom.io/unom/punktfunk.git && cd punktfunk +cargo build --release -p punktfunk-host +``` + +Then write `~/.config/punktfunk/host.env` (as in `/usr/share/punktfunk/host.env.kde`, but the host +binary is `target/release/punktfunk-host`) and run it inside your desktop session — for a headless +KWin appliance see [KDE → Headless session](/docs/kde#headless-session). diff --git a/docs-site/content/docs/forgot-password.md b/docs-site/content/docs/forgot-password.md index aa90779..5d7e4dd 100644 --- a/docs-site/content/docs/forgot-password.md +++ b/docs-site/content/docs/forgot-password.md @@ -8,21 +8,20 @@ password. That password is generated — or, on Windows, chosen — when the con it lives on the **host**. So if you can't get past the login screen, you recover or change it on the host machine itself, not from the browser. +New to the console? See [The Web Console](/docs/web-console) to enable it and arm pairing. + > This is **only** the web console login. It is **not** your client/device pairing — if a client > won't connect, that's [Pairing](/docs/pairing), not this password. ## Find your host -Jump to your host platform for exactly where the password lives and how to read or reset it: +Find your host platform for exactly where the password lives, then read or reset it below: | Host | Where the password lives | Section | |------|--------------------------|---------| -| **Ubuntu — GNOME** | `~/.config/punktfunk/web-password` | [Console login password](/docs/ubuntu-gnome#console-login-password) | -| **Ubuntu — KDE Plasma** | `~/.config/punktfunk/web-password` | [Console login password](/docs/ubuntu-kde#console-login-password) | -| **Fedora — KDE Plasma** | `~/.config/punktfunk/web-password` | [Console login password](/docs/fedora-kde#console-login-password) | -| **Bazzite — gamescope** | `~/.config/punktfunk/web-password` | [Console login password](/docs/bazzite#console-login-password) | -| **SteamOS (host)** | `~/.config/punktfunk/web.env` | [Console login password](/docs/steamos-host#console-login-password) | -| **Windows host** | `%ProgramData%\punktfunk\web-password` | [Console login password](/docs/windows-host#console-login-password) | +| **Linux packages (apt / RPM / Bazzite)** | `~/.config/punktfunk/web-password` | [Login password](/docs/web-console#login-password) | +| **SteamOS (host)** | `~/.config/punktfunk/web.env` | [Login password](/docs/web-console#login-password) | +| **Windows host** | `%ProgramData%\punktfunk\web-password` | [Login password](/docs/web-console#login-password) · [Windows Host](/docs/windows-host) | ## The short version diff --git a/docs-site/content/docs/gamescope.md b/docs-site/content/docs/gamescope.md new file mode 100644 index 0000000..7b2c4a5 --- /dev/null +++ b/docs-site/content/docs/gamescope.md @@ -0,0 +1,77 @@ +--- +title: Steam / gamescope +description: 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](/docs/bazzite) or [SteamOS (Host)](/docs/steamos-host). + +> New here? Read [Security & Safe Use](/docs/security) 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. 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**. + +## 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, start it from your session — the default attach model +just latches onto whatever gamescope session is live: + +```sh +systemctl --user enable --now punktfunk-host +``` + +Then bring up [The Web Console](/docs/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](/docs/configuration) for every other knob. + +| Setting | Values | Meaning | +|---|---|---| +| `PUNKTFUNK_GAMESCOPE_ATTACH` | `1` | **Attach** model: the box owns its gamescope session; the host captures whatever's live and never tears it down. Streamed resolution is the box's gamescope mode. The default. | +| `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 mode, restoring on idle. 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 — 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. +- **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](/docs/kde). To bring up the +web console and pair a client, see [The Web Console](/docs/web-console). diff --git a/docs-site/content/docs/gnome.md b/docs-site/content/docs/gnome.md new file mode 100644 index 0000000..83195fe --- /dev/null +++ b/docs-site/content/docs/gnome.md @@ -0,0 +1,96 @@ +--- +title: GNOME (Mutter) +description: Configure a punktfunk host for GNOME — host.env, the EGL/lock traps, and a headless session. +--- + +Configure a host running **GNOME**. The host drives GNOME's Mutter compositor to create a per-client +virtual display over D-Bus (`RecordVirtual`), zero-copy. This page assumes the host is already +installed — see [Ubuntu](/docs/ubuntu), [Fedora](/docs/fedora), or [Arch](/docs/arch). + +> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of +> the machine, so keep it on a trusted LAN or VPN and require pairing. + +## host.env + +Write `~/.config/punktfunk/host.env` with the GNOME settings. The host auto-detects the compositor +from your session, so the explicit `PUNKTFUNK_COMPOSITOR` is belt-and-braces: + +```ini +# ~/.config/punktfunk/host.env +WAYLAND_DISPLAY=wayland-0 +XDG_CURRENT_DESKTOP=GNOME +PUNKTFUNK_COMPOSITOR=mutter +PUNKTFUNK_VIDEO_SOURCE=virtual +PUNKTFUNK_ZEROCOPY=1 +PUNKTFUNK_INPUT_BACKEND=libei +``` + +You must be on a **Wayland** session (not X11), and Mutter must be **≥ 48**. See the +[Configuration reference](/docs/configuration) for every option. + +## The GL/EGL userspace + +On NVIDIA, gnome-shell fails to start — or the host logs **"GPU … not supported by EGL"** — when the +NVIDIA GL/EGL userspace is missing. The base driver package doesn't always pull it in. Install your +distro's NVIDIA GL/EGL userspace package — on **Ubuntu/Debian** it's `libnvidia-gl-` matching +your driver; on **Fedora/Arch** it ships with the RPM Fusion / repo driver — then confirm the glvnd +vendor file exists: + +```sh +ls /usr/share/glvnd/egl_vendor.d/10_nvidia.json # must exist +``` + +Installing the driver itself is covered on your distro's install page +([Ubuntu](/docs/ubuntu), [Fedora](/docs/fedora), [Arch](/docs/arch)). + +## Do not lock the session + +A **locked** GNOME session blocks screen capture — the host fails with +**"Session creation inhibited"**. On an always-on or headless host there's no one to unlock it, so +disable the lock: + +```sh +gsettings set org.gnome.desktop.screensaver lock-enabled false +gsettings set org.gnome.desktop.session idle-delay 0 +``` + +## Start the host + +With `host.env` in place, start the host from **inside your GNOME session**: + +```sh +systemctl --user enable --now punktfunk-host +journalctl --user -u punktfunk-host -f # watch it come up and print its identity fingerprint +``` + +Then bring up [The Web Console](/docs/web-console) to arm pairing and connect a +[client](/docs/clients). For an always-on box, see the [headless session](#headless-session) below. + +## Headless session + +To run with no monitor and no login, keep a GNOME Wayland session up at all times and start the host +without a login. Have GDM auto-login your user: + +```ini +# /etc/gdm3/custom.conf (Ubuntu) · /etc/gdm/custom.conf (Fedora) +[daemon] +AutomaticLoginEnable = true +AutomaticLogin = your-user +``` + +Disable the lock (see [above](#do-not-lock-the-session)), then enable the host user service and let it +linger past logout: + +```sh +systemctl --user enable --now punktfunk-host +sudo loginctl enable-linger "$USER" +``` + +Reboot and the host comes up on the auto-login session. Full walkthrough: +[Running as a Service](/docs/running-as-a-service). + +## Troubleshooting + +More fixes — black screen, discovery, pairing — in [Troubleshooting](/docs/troubleshooting). + +Once the host is up, bring the console up and pair — see [The Web Console](/docs/web-console). diff --git a/docs-site/content/docs/how-it-works.md b/docs-site/content/docs/how-it-works.md index e03882d..016c564 100644 --- a/docs-site/content/docs/how-it-works.md +++ b/docs-site/content/docs/how-it-works.md @@ -68,4 +68,4 @@ LAN. ## Multiple devices at once A host can stream to several clients simultaneously — your laptop and your TV both viewing (and -controlling) the desktop, each at its own resolution. See [Multiple devices](/docs/configuration#multiple-devices). +controlling) the desktop, each at its own resolution. See [Multiple devices](/docs/configuration#multiple-devices-at-once). diff --git a/docs-site/content/docs/index.mdx b/docs-site/content/docs/index.mdx index 87b2ad1..878b06d 100644 --- a/docs-site/content/docs/index.mdx +++ b/docs-site/content/docs/index.mdx @@ -29,7 +29,7 @@ It's built for the things that make streaming feel native: - + @@ -37,7 +37,7 @@ It's built for the things that make streaming feel native: ## What you need - A **host** with a supported GPU — either a **Linux** machine running one of the - [supported setups](/docs/requirements) (**Ubuntu** GNOME or KDE, **Fedora** KDE, or **Bazzite**), or + [supported setups](/docs/requirements) (**Ubuntu**, **Fedora**, **Arch**, or **Bazzite**), or a **[Windows](/docs/windows-host) PC**. - A **client device** to stream to — there are native apps for **macOS, iOS/iPadOS, tvOS, Linux, Windows, and Android**, plus any device that runs **Moonlight**. diff --git a/docs-site/content/docs/install.md b/docs-site/content/docs/install.md index 8c464c3..c0c1c6f 100644 --- a/docs-site/content/docs/install.md +++ b/docs-site/content/docs/install.md @@ -16,9 +16,9 @@ On **Windows**, the host ships as a signed installer instead — see [Windows](# | Distro | Package manager | One-command happy path | Guide | |--------|-----------------|------------------------|-------| -| **Ubuntu / Debian** | apt | `sudo apt install punktfunk-host` | [Ubuntu — GNOME](/docs/ubuntu-gnome) · [Ubuntu — KDE](/docs/ubuntu-kde) · [packaging/debian](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/debian/README.md) | +| **Ubuntu / Debian** | apt | `sudo apt install punktfunk-host` | [Ubuntu / Debian](/docs/ubuntu) · [packaging/debian](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/debian/README.md) | | **Bazzite / Fedora Atomic** | systemd-sysext | `sudo bash punktfunk-sysext.sh install` (no layering, no reboot) | [Bazzite](/docs/bazzite) · [packaging/bazzite](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/bazzite/README.md) | -| **Fedora (dnf)** | dnf / rpm-ostree | `dnf install punktfunk punktfunk-web` | [Fedora — KDE](/docs/fedora-kde) · [packaging/rpm](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/rpm/README.md) | +| **Fedora (dnf)** | dnf / rpm-ostree | `dnf install punktfunk punktfunk-web` | [Fedora](/docs/fedora) · [packaging/rpm](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/rpm/README.md) | | **Arch** | pacman | `pacman -Sy punktfunk-host` (binary repo) | [Arch Linux](/docs/arch) · [packaging/arch](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/arch/README.md) | | **SteamOS (host)** | on-device script | `bash scripts/steamdeck/install.sh` | [SteamOS (Host)](/docs/steamos-host) | @@ -79,13 +79,22 @@ fallback without one. More detail — including the CLI `punktfunk-host service Bare `serve` is the secure native-only default (native `punktfunk/1` + the web console). On a trusted LAN, add `--gamestream` to also serve stock [Moonlight](/docs/moonlight) clients. -3. Enable the web console and read its login password, then open `http://:47992`: +3. Enable the web console: ```sh systemctl --user enable --now punktfunk-web - journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p' ``` + Then open `http://:47992`. Reading its [login password](/docs/web-console#login-password) + and [arming PIN pairing](/docs/web-console#arm-pairing) are covered in + [The Web Console](/docs/web-console). + +### Configure your desktop + +How the virtual display and input work depends on your desktop — see [KDE](/docs/kde), +[GNOME](/docs/gnome), [Steam / gamescope](/docs/gamescope), or [Sway](/docs/sway) for the +compositor-specific setup. + From there, follow the [Quick Start](/docs/quickstart) to pair your first client. To run the host automatically at boot, see [Running as a Service](/docs/running-as-a-service). diff --git a/docs-site/content/docs/kde.md b/docs-site/content/docs/kde.md new file mode 100644 index 0000000..9d2c1ed --- /dev/null +++ b/docs-site/content/docs/kde.md @@ -0,0 +1,113 @@ +--- +title: KDE Plasma (KWin) +description: Configure a punktfunk host for KDE — host.env, quirks, and a headless KWin session. +--- + +Configure a punktfunk host on **KDE Plasma**. The host uses KDE's KWin compositor to create a +per-client virtual display, captured zero-copy on NVIDIA. This page assumes the package is already +installed — see [Ubuntu](/docs/ubuntu), [Fedora](/docs/fedora), [Arch](/docs/arch), or the +[Bazzite](/docs/bazzite) appliance. + +> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of +> the machine, so keep it on a trusted LAN or VPN and require pairing. + +## host.env + +A KDE starter `~/.config/punktfunk/host.env`: + +```ini +WAYLAND_DISPLAY=wayland-0 +XDG_CURRENT_DESKTOP=KDE +PUNKTFUNK_COMPOSITOR=kwin +PUNKTFUNK_VIDEO_SOURCE=virtual +PUNKTFUNK_ZEROCOPY=1 +PUNKTFUNK_INPUT_BACKEND=libei +``` + +The host auto-detects the running compositor on every connect, so most of this is optional — the +values above are just what it resolves to on a KWin session. See the +[Configuration reference](/docs/configuration) for every option. + +## Use a Wayland session + +KDE must run on **Wayland**, not X11 — pick the Wayland session from the picker on the login screen. +The virtual-display path is Wayland-only and will not come up under X11. + +KWin must be **6.5.6 or newer** (virtual outputs land there). Check with: + +```sh +kwin_wayland --version +``` + +## Streaming the interactive desktop + +To stream a logged-in Plasma desktop (rather than a headless session, below), KWin has to hand the +host its restricted screencast protocol. The host package ships an `io.unom.Punktfunk.Host.desktop` +file whose `X-KDE-Wayland-Interfaces` grants exactly that on a normal interactive session +(least-privilege, the same mechanism krfb/krdp use). After a **fresh install, log out and back into +the Desktop session once** so KWin re-reads the grant. + +A normal KDE login still lacks the RemoteDesktop grant that **input** injection needs — without it the +host pops an "Allow remote control?" dialog no headless box can answer. **Fedora and Bazzite** ship a +one-shot helper that seeds it (run once as the streaming user, no root): + +```sh +bash /usr/share/punktfunk/bazzite/kde-desktop-setup.sh # Fedora / Bazzite +``` + +The `.deb` and Arch packages don't include that wrapper. Seed the grant by hand instead — copy the +shipped `kde-authorized` file into the portal store (the share dir is `/usr/share/punktfunk-host` on +Debian/Ubuntu, `/usr/share/punktfunk` on Arch), then log out and back in: + +```sh +mkdir -p ~/.local/share/flatpak/db +cp /usr/share/punktfunk*/headless/kde-authorized ~/.local/share/flatpak/db/kde-authorized +``` + +A login-less appliance skips all of this — its headless session (below) needs none of these grants. + +## Start the host + +With `host.env` in place, start the host from **inside your Plasma session**: + +```sh +systemctl --user enable --now punktfunk-host +journalctl --user -u punktfunk-host -f # watch it come up and print its identity fingerprint +``` + +Then bring up [The Web Console](/docs/web-console) to arm pairing and connect a +[client](/docs/clients). To start at boot — including fully headless — see the +[headless session](#headless-session) below or [Running as a Service](/docs/running-as-a-service). + +## Persistent per-client scaling + +KWin round-trips per-client display scale: it names each session's virtual output per client, so a +scale you set for one client (150 %, 125 %, …) is reapplied on that client's next connect. See +[Virtual displays](/docs/virtual-displays). + +## Headless session + +For a login-less appliance — a box that streams at boot with no graphical login — the host brings up a +**dedicated headless KWin session** rather than relying on an interactive one. It runs its own +`kwin --virtual` session (shipped as the `punktfunk-kde-session.service` unit) with permission checks +relaxed, so it needs none of the interactive grants above. + +```sh +mkdir -p ~/.config/punktfunk +cp /usr/share/punktfunk/host.env.kde ~/.config/punktfunk/host.env # Debian/Ubuntu: /usr/share/punktfunk-host/host.env.kde + +systemctl --user daemon-reload +systemctl --user enable --now punktfunk-kde-session punktfunk-host +sudo loginctl enable-linger "$USER" +``` + +The session unit brings up headless KWin; the host unit follows it and starts listening. See +[Running as a Service](/docs/running-as-a-service) for the full headless setup. + +## Troubleshooting + +- **KWin too old:** virtual outputs need KWin **≥ 6.5.6**. Check with `kwin_wayland --version`. +- **Black screen / no picture:** confirm you're on a Wayland session (not X11) and the NVIDIA GL + userspace is installed. More in [Troubleshooting](/docs/troubleshooting). + +To bring the console up and pair, see [The Web Console](/docs/web-console). diff --git a/docs-site/content/docs/meta.json b/docs-site/content/docs/meta.json index 7deedcf..f6fbe32 100644 --- a/docs-site/content/docs/meta.json +++ b/docs-site/content/docs/meta.json @@ -5,27 +5,31 @@ "how-it-works", "security", "quickstart", - "install", - "---Host Setup---", + "---Install the host---", "requirements", - "ubuntu-gnome", - "ubuntu-kde", - "fedora-kde", + "install", + "ubuntu", + "fedora", "arch", "bazzite", "steamos-host", "windows-host", + "web-console", + "---Configure your desktop---", + "configuration", + "kde", + "gnome", + "gamescope", + "sway", "running-as-a-service", + "virtual-displays", + "host-cli", "---Connecting---", "clients", "install-client", "steam-deck", "moonlight", "pairing", - "---Configuration---", - "configuration", - "virtual-displays", - "host-cli", "---Troubleshooting---", "troubleshooting", "stats", diff --git a/docs-site/content/docs/quickstart.md b/docs-site/content/docs/quickstart.md index 07b8f41..ebf3b03 100644 --- a/docs-site/content/docs/quickstart.md +++ b/docs-site/content/docs/quickstart.md @@ -11,15 +11,19 @@ This is the shortest path to a working stream. Each step links to the details. ## 1. Set up the host -On your Linux gaming machine (NVIDIA, AMD, or Intel GPU), follow the guide for your system: +On your gaming machine (NVIDIA, AMD, or Intel GPU), follow the install guide for your system: -- [Ubuntu — GNOME](/docs/ubuntu-gnome) -- [Ubuntu — KDE Plasma](/docs/ubuntu-kde) -- [Fedora — KDE Plasma](/docs/fedora-kde) -- [Bazzite — gamescope / Steam](/docs/bazzite) +- [Ubuntu / Debian](/docs/ubuntu) +- [Fedora](/docs/fedora) +- [Arch](/docs/arch) +- [Bazzite](/docs/bazzite) +- [SteamOS](/docs/steamos-host) +- [Windows host](/docs/windows-host) -Each one covers the GPU driver, the dependencies, and how to build and run the host. Check the -[Requirements](/docs/requirements) first if you're not sure your machine is a fit. +Each one covers the GPU driver, the dependencies, and how to install and run the host. After +installing, configure for your desktop ([KDE](/docs/kde) / [GNOME](/docs/gnome) / +[gamescope](/docs/gamescope) / [Sway](/docs/sway)). Check the [Requirements](/docs/requirements) +first if you're not sure your machine is a fit. ## 2. Start the host @@ -44,9 +48,9 @@ latency, or any Moonlight client: the list of hosts found on your network. Select it, and when prompted, **pair**. - **Anything with Moonlight:** add the host (it should be discovered automatically), then pair. -To pair, the host needs to show a PIN. Arm pairing from the host's web console — the host displays a -4-digit PIN, you type it into the client, and they trust each other from then on. Pairing is required -by default. Full details: [Pairing & Trust](/docs/pairing). +To pair, the host needs to show a PIN. [Arm pairing](/docs/web-console#arm-pairing) from the host's +web console — the host displays a 4-digit PIN, you type it into the client, and they trust each other +from then on. Pairing is required by default. Full details: [Pairing & Trust](/docs/pairing). ## 4. Stream diff --git a/docs-site/content/docs/requirements.md b/docs-site/content/docs/requirements.md index f6f17f6..98e1b27 100644 --- a/docs-site/content/docs/requirements.md +++ b/docs-site/content/docs/requirements.md @@ -6,19 +6,31 @@ description: What you need to run a punktfunk host — GPU, driver, desktop, and ## Supported setups A punktfunk host runs primarily on a Linux machine with a dedicated GPU — NVIDIA (NVENC) is the -most-exercised path, and AMD/Intel GPUs work via VAAPI (a native -[Windows host](/docs/windows-host) is also available — see below). These are the Linux desktop -environments it supports today, each with its own guide: +most-exercised path, and AMD/Intel GPUs work via VAAPI. A native [Windows host](/docs/windows-host) +is also available. Setup splits along two axes: you **install** the package per distro, then +**configure** the host — and learn its quirks — per desktop/compositor. -| Setup | Desktop / compositor | Guide | -|---|---|---| -| **Ubuntu** (Desktop or Server) | GNOME (Mutter) | [Ubuntu — GNOME](/docs/ubuntu-gnome) | -| **Ubuntu** (Desktop or Server) | KDE Plasma (KWin) | [Ubuntu — KDE](/docs/ubuntu-kde) | -| **Fedora** | KDE Plasma (KWin) | [Fedora — KDE](/docs/fedora-kde) | -| **Bazzite** | gamescope (Steam) | [Bazzite](/docs/bazzite) | +> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of +> the machine, so keep it on a trusted LAN or VPN and require pairing. -Other wlroots compositors (Sway/Hyprland) also work but aren't a primary target. If your desktop isn't -listed, the host still needs one of these compositor backends to create a virtual display. +**Distros — install the package:** + +- [Ubuntu / Debian](/docs/ubuntu) +- [Fedora](/docs/fedora) +- [Arch](/docs/arch) +- [Bazzite](/docs/bazzite) +- [SteamOS](/docs/steamos-host) + +**Desktops — configure and quirks:** + +- [KDE Plasma (KWin)](/docs/kde) +- [GNOME (Mutter)](/docs/gnome) +- [Steam / gamescope](/docs/gamescope) +- [Sway / wlroots](/docs/sway) + +Pick your distro to install, then your desktop to configure — the two are independent. Other +wlroots compositors (Hyprland) work but aren't a primary target; the host still needs one of these +compositor backends to create a virtual display. > **Windows host:** punktfunk also runs as a native host on **Windows 11 22H2 or newer (x64)** — a > signed installer that registers a service and bundles a virtual-display driver (whose driver- @@ -32,8 +44,8 @@ listed, the host still needs one of these compositor backends to create a virtua encodes the video in hardware. - **NVIDIA driver 535 or newer** (550+ recommended). The driver must include the **GL/EGL userspace**, not just `nvidia-utils` — without it the compositor can't initialise the GPU and capture fails. Each - setup guide installs the right package (e.g. `libnvidia-gl-` on Ubuntu). -- **`nvidia-drm modeset=1`** must be enabled (Wayland on NVIDIA needs it). The setup guides cover this. + install guide installs the right package (e.g. `libnvidia-gl-` on Ubuntu). +- **`nvidia-drm modeset=1`** must be enabled (Wayland on NVIDIA needs it). The install guides cover this. - **AMD / Intel GPUs** encode via **VAAPI** instead (install `mesa-va-drivers` or `intel-media-driver`; validated live on AMD RDNA3). The NVIDIA-specific notes above don't apply there. On modern Intel (Gen12/Tiger Lake and newer, including Arc) the driver only offers the @@ -57,9 +69,9 @@ needs to be running for the user the host runs as. This can be: Minimum compositor versions (newer is fine): -- **KWin ≥ 6.5.6** (KDE Plasma) — headless virtual outputs. -- **GNOME ≥ 48** (Mutter) — virtual-monitor screen-cast. -- **gamescope ≥ 3.16.22** (Bazzite/Steam) — older versions deadlock during capture. +- **KWin ≥ 6.5.6** ([KDE Plasma](/docs/kde)) — headless virtual outputs. +- **GNOME ≥ 48** ([Mutter](/docs/gnome)) — virtual-monitor screen-cast. +- **gamescope ≥ 3.16.22** ([Bazzite/Steam](/docs/gamescope)) — older versions deadlock during capture. ## Network @@ -70,10 +82,6 @@ Minimum compositor versions (newer is fine): - For best results, a wired or fast Wi-Fi link. The host can run a built-in **speed test** to pick a bitrate for your link (see [Configuration](/docs/configuration)). -> **Before you set up a host, read [Security & Safe Use](/docs/security).** A streaming host is -> remote control of the machine — it's important to understand what that exposes, why to keep it on a -> trusted network, and how pairing protects you. - ## A client You also need something to stream *to* — see [Connect a Client](/docs/clients). There are native diff --git a/docs-site/content/docs/running-as-a-service.md b/docs-site/content/docs/running-as-a-service.md index e2c3ddb..64a4aaa 100644 --- a/docs-site/content/docs/running-as-a-service.md +++ b/docs-site/content/docs/running-as-a-service.md @@ -37,50 +37,21 @@ Start by making the host service start at boot even when nobody logs in: sudo loginctl enable-linger "$USER" ``` -Then bring up a session automatically, depending on your desktop: +Then bring up a session automatically. How you do that is desktop-specific — auto-login, lock +disable, and the session unit differ per compositor, so each is documented on its own page: -### Headless GNOME +- GNOME: [GNOME → Headless session](/docs/gnome#headless-session). +- KDE Plasma: [KDE → Headless session](/docs/kde#headless-session). +- Steam / gamescope: [gamescope](/docs/gamescope) — the host launches its own session per client, so + there's no separate session unit. -Have GDM auto-login your user, so a GNOME Wayland session is always running: - -```ini -# /etc/gdm3/custom.conf (Ubuntu) · /etc/gdm/custom.conf (Fedora) -[daemon] -AutomaticLoginEnable = true -AutomaticLogin = your-user -``` - -Then **disable the screen lock** — a locked GNOME session blocks screen capture, and there's no one to -unlock a headless box: - -```sh -gsettings set org.gnome.desktop.screensaver lock-enabled false -gsettings set org.gnome.desktop.session idle-delay 0 -``` - -Enable the host user service (section A) and reboot. The host comes up on the auto-login session. - -### Headless KDE - -punktfunk ships a unit that brings up a headless KWin/Plasma session with no display manager, so the -host has a desktop to stream even with no monitor attached: - -```sh -cp scripts/punktfunk-kde-session.service scripts/punktfunk-host.service ~/.config/systemd/user/ -# host.env: PUNKTFUNK_COMPOSITOR=kwin, WAYLAND_DISPLAY=wayland-kde -systemctl --user daemon-reload -systemctl --user enable punktfunk-kde-session punktfunk-host -sudo loginctl enable-linger "$USER" -reboot -``` - -The session unit starts headless KWin; the host unit follows it and starts listening. (KWin only needs -to be up by the time a client connects, so the ordering is soft.) +Once a session comes up at boot, enable the host user service (section A) and reboot. The host comes up +on that session. ### Headless Bazzite On Bazzite, the host launches its own gamescope/Steam session per client, so you don't need a separate -session unit — see [Bazzite](/docs/bazzite). +session unit — see [Bazzite](/docs/bazzite) and [gamescope](/docs/gamescope). ## Windows diff --git a/docs-site/content/docs/steamos-host.md b/docs-site/content/docs/steamos-host.md index 4643393..293aa0c 100644 --- a/docs-site/content/docs/steamos-host.md +++ b/docs-site/content/docs/steamos-host.md @@ -86,9 +86,8 @@ When it finishes it prints the web-console URL and how to pair. By default the host **requires PIN pairing** (secure). Two ways to pair: -- **Web console** (printed at the end of step 2): open `http://:47992`, log in with the - generated password (in `~/.config/punktfunk/web.env`), go to **Devices → arm pairing**, and enter - the PIN on your client. +- **Web console** (printed at the end of step 2): open `http://:47992`, + [arm pairing](/docs/web-console#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. @@ -96,17 +95,9 @@ On a trusted home LAN you can instead install with `--open` and skip pairing ent ### 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). +The installer generates a random console login password (printed at the end of step 2) and writes it +to `~/.config/punktfunk/web.env`. To read it back or set your own, see +[The Web Console](/docs/web-console#login-password). ## 4. Verify @@ -118,7 +109,8 @@ 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. +auto-detects which session is live per connection. See [Steam / gamescope](/docs/gamescope) for the +attach-vs-managed detail and known limits. ## Updating diff --git a/docs-site/content/docs/sway.md b/docs-site/content/docs/sway.md new file mode 100644 index 0000000..81a2fc2 --- /dev/null +++ b/docs-site/content/docs/sway.md @@ -0,0 +1,68 @@ +--- +title: Sway / wlroots +description: Configure a punktfunk host on a wlroots compositor (Sway, Hyprland). +--- + +The wlroots family can host — but **Sway is the only validated path.** The host adds a per-client +headless output at the client's exact mode and captures it through the xdg-desktop-portal-wlr (xdpw) +ScreenCast portal, injecting input via the wlroots virtual pointer/keyboard protocols. Hyprland and +other wlroots compositors are best-effort (see [How it works](#how-it-works) for the caveat). + +This is **not a primary target.** It works and is validated live on **sway 1.11** (zero-copy), but it +sees far less testing than the KDE and GNOME paths — expect rougher edges. If you have a choice, +[KDE](/docs/kde) or [GNOME](/docs/gnome) are the better-exercised desktops. + +This page assumes the package is already installed — see [Arch](/docs/arch), [Ubuntu](/docs/ubuntu), +or [Fedora](/docs/fedora). + +> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of +> the machine, so keep it on a trusted LAN or VPN and require pairing. + +## host.env + +The host auto-detects a wlroots session, so you usually need nothing here. To force the backend, set +these in `~/.config/punktfunk/host.env`: + +```ini +PUNKTFUNK_COMPOSITOR=wlroots # aliases: sway, hyprland +PUNKTFUNK_INPUT_BACKEND=wlr +PUNKTFUNK_VIDEO_SOURCE=virtual +PUNKTFUNK_ZEROCOPY=1 # GPU zero-copy capture→encode; auto-falls back to CPU +``` + +See [Configuration](/docs/configuration) for the full reference. + +## How it works + +- **Video** — the host adds a headless output at the client's exact mode with `swaymsg create_output`. + This uses Sway's IPC specifically; other wlroots compositors (Hyprland, …) don't expose an + equivalent, so virtual-output creation isn't wired up for them yet — Sway is the supported wlroots + path today. +- **Capture** — it captures that output through the **xdg-desktop-portal-wlr (xdpw)** ScreenCast + portal. The host writes a managed chooser config so the output pick is automatic — no interactive + picker dialog to answer. +- **Input** — mouse and keyboard are injected via the wlroots **virtual pointer** and **virtual + keyboard** protocols. + +For how long the virtual output lives, and extend-vs-exclusive topology, see +[Virtual displays](/docs/virtual-displays). + +## Requirements + +- A running wlroots session (Sway, Hyprland, …). +- **xdg-desktop-portal-wlr (xdpw)** installed and running — the host captures through its ScreenCast + portal. Without it there is no video. + +## Start the host + +With the backend selected, start the host from **inside your Sway session**: + +```sh +systemctl --user enable --now punktfunk-host +journalctl --user -u punktfunk-host -f +``` + +## Bring up the console and pair + +Enable the web console, read its login password, and arm PIN pairing — see +[The Web Console](/docs/web-console). Then [connect a client](/docs/clients). diff --git a/docs-site/content/docs/troubleshooting.md b/docs-site/content/docs/troubleshooting.md index 94792e4..6e27707 100644 --- a/docs-site/content/docs/troubleshooting.md +++ b/docs-site/content/docs/troubleshooting.md @@ -71,10 +71,14 @@ The NVIDIA **GL/EGL userspace** is missing — the base driver package doesn't a - **Ubuntu:** `sudo apt install libnvidia-gl-` (matching your driver). - Confirm `/usr/share/glvnd/egl_vendor.d/10_nvidia.json` exists and `nvidia-drm modeset` is `Y`. +See [GNOME](/docs/gnome) for the GL/EGL userspace details. + ## Black screen / no picture, but the client connects - You must be on a **Wayland** session, not X11 (check the login-screen session picker). -- KWin must be **≥ 6.5.6** (`kwin_wayland --version`); GNOME **≥ 48**; gamescope **≥ 3.16.22**. +- KWin must be **≥ 6.5.6** (`kwin_wayland --version`); GNOME **≥ 48**; gamescope **≥ 3.16.22**. See + [KDE](/docs/kde) for the KWin/Wayland requirement and [gamescope](/docs/gamescope) for the + gamescope one. - Confirm `PUNKTFUNK_COMPOSITOR` in [`host.env`](/docs/configuration) matches your desktop. ## Capture fails: "Session creation inhibited" (GNOME) @@ -86,7 +90,8 @@ gsettings set org.gnome.desktop.screensaver lock-enabled false gsettings set org.gnome.desktop.session idle-delay 0 ``` -See [Running as a Service](/docs/running-as-a-service). +See [GNOME → Headless session](/docs/gnome#headless-session) and +[Running as a Service](/docs/running-as-a-service). ## A controller is detected but does nothing (Bazzite) @@ -96,7 +101,8 @@ The host user needs to be in the `input` group. On Bazzite: ujust add-user-to-input-group ``` -Then log out and back in. On other distros this is `sudo usermod -aG input $USER` + re-login. +Then log out and back in. On other distros this is `sudo usermod -aG input $USER` + re-login. See +[Bazzite](/docs/bazzite). ## Pairing is rejected / the client can't connect diff --git a/docs-site/content/docs/ubuntu.md b/docs-site/content/docs/ubuntu.md new file mode 100644 index 0000000..9b18672 --- /dev/null +++ b/docs-site/content/docs/ubuntu.md @@ -0,0 +1,133 @@ +--- +title: Ubuntu / Debian +description: Install the punktfunk host on Ubuntu or Debian with apt. +--- + +Install a punktfunk host on **Ubuntu** (Desktop or Server) or **Debian** from the apt registry. This +page covers the distro-level setup — GPU driver, package, gamepad access. It works with either GNOME +or KDE; how the host creates its virtual display and injects input is desktop-specific, so pick your +desktop on the [configure pages](#configure-your-desktop) afterward rather than here. + +> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of +> the machine, so keep it on a trusted LAN or VPN and require pairing. + +## 1. GPU driver + +On **NVIDIA**, install the recommended driver: + +```sh +sudo ubuntu-drivers install # or: sudo apt install nvidia-driver- +``` + +Then make sure the **GL/EGL userspace** is present — Wayland compositors on NVIDIA need it, and the +base driver package doesn't always pull it in. Install the `libnvidia-gl` package matching your +driver version: + +```sh +sudo apt install libnvidia-gl- # e.g. libnvidia-gl-550 +``` + +Reboot, then confirm the driver and KMS modeset: + +```sh +nvidia-smi +cat /sys/module/nvidia_drm/parameters/modeset # should print Y +``` + +If modeset is not `Y`: + +```sh +echo 'options nvidia-drm modeset=1' | sudo tee /etc/modprobe.d/nvidia-drm.conf +sudo update-initramfs -u && sudo reboot +``` + +> **Secure Boot:** on a machine with Secure Boot **enabled**, the NVIDIA kernel module won't load +> until you enrol its signing key. If `nvidia-smi` reports it can't talk to the driver, run +> `sudo mokutil --import /var/lib/shim-signed/mok/MOK.der` (set a one-time password), reboot, and +> choose **Enrol MOK** at the blue screen. Or disable Secure Boot in firmware. + +On **AMD/Intel** none of the NVIDIA steps apply. Encode runs through VAAPI on the Mesa stack — +`mesa-va-drivers` on AMD, `intel-media-driver` on Intel — which your desktop install already provides. + +## 2. Install the host (apt) + +`punktfunk-host` is published as a `.deb` to the public Gitea apt registry, so the box installs and +updates with plain `apt`. The registry is public — no auth needed, just trust its signing key: + +```sh +sudo install -d -m 0755 /etc/apt/keyrings +curl -fsSL https://git.unom.io/api/packages/unom/debian/repository.key \ + | sudo tee /etc/apt/keyrings/punktfunk.asc >/dev/null + +echo "deb [signed-by=/etc/apt/keyrings/punktfunk.asc] https://git.unom.io/api/packages/unom/debian stable main" \ + | sudo tee /etc/apt/sources.list.d/punktfunk.list + +sudo apt update +sudo apt install punktfunk-host +``` + +`punktfunk-host` `Recommends` the browser console (`punktfunk-web`), so apt pulls it in by default. +The desktop *client* (`punktfunk-client`) is a separate package for the machine you stream *to* — not +installed on a host. The NVIDIA driver is **not** a dependency — you installed it out of band in +step 1. Later updates are just `sudo apt update && sudo apt upgrade`. + +The `stable` component above is the stable channel. To track pre-release builds instead, see +[Release Channels](/docs/channels). + +## 3. Grant gamepad access + +Virtual gamepads inject through `/dev/uinput`, which is gated by the `input` group. Add yourself and +re-login so the new group membership takes effect: + +```sh +sudo usermod -aG input "$USER" # re-login to apply +``` + +## Configure your desktop + +How the host creates its virtual display and injects input depends on your desktop, not your distro. +Continue on the page for the desktop you run — it covers your `host.env`, any compositor quirks, and +starting the host: + +- [KDE Plasma (KWin)](/docs/kde) +- [GNOME (Mutter)](/docs/gnome) +- [Steam / gamescope](/docs/gamescope) +- [Sway / wlroots](/docs/sway) + +Then bring up [The Web Console](/docs/web-console) to arm pairing and connect your first +[client](/docs/clients). To run the host at boot — including fully **headless** — see +[Running as a Service](/docs/running-as-a-service). + +## Appendix — build from source + +If the apt registry doesn't have a build for your release, or you want to track `main` directly, +compile the host yourself (no clean updates / no packaged units — you wire those up by hand). + +Install the build toolchain and runtime libraries: + +```sh +sudo apt install build-essential pkg-config cmake clang libclang-dev nasm git curl \ + pipewire pipewire-pulse wireplumber libpipewire-0.3-dev libspa-0.2-dev \ + libwayland-dev wayland-protocols libxkbcommon-dev libopus-dev \ + libdrm-dev libgbm-dev libegl-dev libgles-dev mesa-common-dev libva-dev \ + ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavfilter-dev libavdevice-dev \ + libnvidia-egl-wayland1 libnvidia-egl-gbm1 libei-dev +``` + +Install Rust if you don't have it, then build: + +```sh +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +git clone https://git.unom.io/unom/punktfunk.git && cd punktfunk +cargo build --release -p punktfunk-host +``` + +The host binary lands at `target/release/punktfunk-host`. Configure your desktop as above, then run +it from inside your session: + +```sh +cargo run --release -p punktfunk-host -- serve --gamestream +``` + +(The native plane is always on; `--gamestream` adds the Moonlight-compat surface — trusted LAN only. +Drop it for a secure native-only host.) diff --git a/docs-site/content/docs/web-console.md b/docs-site/content/docs/web-console.md new file mode 100644 index 0000000..a466444 --- /dev/null +++ b/docs-site/content/docs/web-console.md @@ -0,0 +1,73 @@ +--- +title: The Web Console +description: Enable the punktfunk browser console, read or change its login password, and arm PIN pairing. +--- + +The web console is the browser UI for a punktfunk host — live status, paired devices, and the PIN +pairing flow. It ships as the **`punktfunk-web`** systemd user unit on Linux and the **`PunktfunkWeb`** +task on Windows, and serves on **`http://:47992`**. The host's own management API stays +loopback-only behind it, so the console is the one surface you expose on the LAN. + +> New here? Read [Security & Safe Use](/docs/security) first — a streaming host is remote control of +> the machine, so keep it on a trusted LAN or VPN and require pairing. + +## Enable the console + +- **Linux packages (apt / RPM / Bazzite):** `punktfunk-host` recommends `punktfunk-web`, so your + package manager pulls it in. Enable and start it as your desktop user, then open the URL: + + ```sh + systemctl --user enable --now punktfunk-web + # then browse to http://:47992 + ``` + +- **Windows host:** the installer sets up the console, its runtime, and the `PunktfunkWeb` task and + starts it at boot. There is nothing to enable — open `http://:47992`. + +- **SteamOS host:** the install script builds and starts the console as a user service for you. It + prints the URL when it finishes. + +## Login password + +The console is password-protected. Where that password lives and how you change it depends on the +host platform. + +**Linux packages (apt / RPM / Bazzite).** On first start `punktfunk-web-init` generates a random +password and saves it to `~/.config/punktfunk/web-password` (as `PUNKTFUNK_UI_PASSWORD=…`). Read it +back from the init service's journal or straight from the file: + +```sh +journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p' +sed -n 's/^PUNKTFUNK_UI_PASSWORD=//p' ~/.config/punktfunk/web-password +``` + +To set your own, edit that file (`PUNKTFUNK_UI_PASSWORD=`) and restart the console: +`systemctl --user restart punktfunk-web`. + +**SteamOS host.** Same idea, but the install script writes the generated password to +`~/.config/punktfunk/web.env` and prints it at the end of the install run: + +```sh +sed -n 's/^PUNKTFUNK_UI_PASSWORD=//p' ~/.config/punktfunk/web.env +``` + +Edit that file and `systemctl --user restart punktfunk-web` to change it. + +**Windows host.** You choose the password during install — a secure random default is pre-filled and +shown again on the installer's final page. It's stored in `%ProgramData%\punktfunk\web-password` (as +`PUNKTFUNK_UI_PASSWORD=…`), readable only by Administrators and SYSTEM. To change it, edit the file +and restart the task in an **elevated** PowerShell: + +```powershell +notepad "$env:ProgramData\punktfunk\web-password" # set PUNKTFUNK_UI_PASSWORD= +schtasks /End /TN PunktfunkWeb; schtasks /Run /TN PunktfunkWeb +``` + +Forgot it? See [Forgot your Password?](/docs/forgot-password). + +## Arm pairing + +The host **requires PIN pairing** by default (secure on a LAN). To connect the first time, open the +console, log in, and go to **Devices → arm pairing**. The host displays a 4-digit PIN — enter it on +your [client](/docs/clients) to pair. See [Pairing & Trust](/docs/pairing) for the full trust model +and how to approve or remove devices later. diff --git a/docs-site/content/docs/windows-host.md b/docs-site/content/docs/windows-host.md index 4fc133c..1bd1f38 100644 --- a/docs-site/content/docs/windows-host.md +++ b/docs-site/content/docs/windows-host.md @@ -59,29 +59,24 @@ Packaging internals live in ### Web console & pairing +See [The Web Console](/docs/web-console) for the console + pairing model shared with the Linux host; +the Windows specifics follow. + The installer also sets up the **web management console** (status, paired devices, the PIN pairing flow): it bundles the console plus its own runtime and runs it as the **`PunktfunkWeb`** task on **`http://:47992`**, starting at boot. #### Console login password -During setup you choose the console **login password** — it's pre-filled with a secure random default -and shown again on the installer's final page. It's stored in `%ProgramData%\punktfunk\web-password` -(as `PUNKTFUNK_UI_PASSWORD=…`), readable only by Administrators and SYSTEM. - -To change it, edit that file and restart the console task. In an **elevated** PowerShell: - -```powershell -notepad "$env:ProgramData\punktfunk\web-password" # set PUNKTFUNK_UI_PASSWORD= -schtasks /End /TN PunktfunkWeb; schtasks /Run /TN PunktfunkWeb -``` - -Forgot it? This is the recovery path linked from the console login screen — see +You choose the console **login password** during setup — a secure random default is pre-filled and +shown on the installer's final page. It's stored in `%ProgramData%\punktfunk\web-password`, readable +only by Administrators and SYSTEM. To read or change it (with the `schtasks` restart), see +[The Web Console → Login password](/docs/web-console#login-password); forgot it entirely? [Forgot your Password?](/docs/forgot-password). The host **requires PIN pairing** by default (secure on a LAN). To connect the first time, open the -console from any browser on the LAN, log in, go to **Devices → arm pairing**, and enter the PIN on -your [client](/docs/clients). The host's own management API stays loopback-only behind the console. +console from any browser on the LAN, log in, go to **Devices → [arm pairing](/docs/web-console#arm-pairing)**, +and enter the PIN on your [client](/docs/clients). The host's own management API stays loopback-only behind the console. ### Configure