docs(dist): end-user install front door + serve/pairing/firewall accuracy fixes

Make the host docs match the real distribution path and the actual CLI. Reviewed by a
multi-agent pass (6 editors against one verified fact sheet + an accuracy reviewer); its
findings (a wrong client-Recommends claim, a native-concurrency overstatement) folded in.

- Install front door: new README "Install (host)" method-picker + docs-site/install.md
  (+ nav), routing each distro to its package registry; source build demoted to a fallback.
- Registry-first install: ubuntu-gnome/ubuntu-kde now lead with the apt registry (not a
  cargo build); bazzite leads with the Gitea RPM registry (was COPR/source). Source builds
  moved to an appendix.
- CLI accuracy: serve --native arms pairing from the web console (NOT --allow-pairing, which
  with --require-pairing/--max-concurrent is m3-host-only); --open disables mandatory pairing.
  host-cli/configuration/pairing/quickstart/troubleshooting corrected; mgmt API documented as
  always HTTPS+token. Native host serves one session at a time (extras queue) — not multi.
- Firewall: real ports documented (native UDP 9777 + the ephemeral data port caveat +
  GameStream ports) for Debian + Arch (ufw + nftables), not just Bazzite.
- Sync/accuracy: punktfunk-client (GTK4) presented as a shipping client (not "roadmap"),
  punktfunk-client-rs as the headless tool; host Recommends punktfunk-web only (not the
  client); COPR chroots f43/44; bootc header says Gitea registry not COPR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 10:43:12 +00:00
parent 5b3d5689bf
commit 9e015304ee
17 changed files with 438 additions and 96 deletions
+47 -5
View File
@@ -13,10 +13,37 @@ the mode of the device you're streaming to, not the TV the box is plugged into.
## Install
The host installs from the punktfunk COPR repository (see `packaging/bazzite/` in the repo for the
exact COPR/RPM/bootc options). You can also build from source as on
[Fedora KDE](/docs/fedora-kde) — Bazzite is Fedora Atomic underneath, and its FFmpeg builds the host
fine.
The host ships as an RPM in punktfunk's **Gitea RPM registry** (public), so a Bazzite / Fedora
Atomic box layers and updates it with `rpm-ostree`. Add the repo, then layer the host plus the web
console and reboot:
```sh
# Add the repo. Our RPMs are unsigned, but Gitea GPG-signs the repo METADATA — verify that
# (repo_gpgcheck=1) and skip the per-package signature check (gpgcheck=0). The signed metadata
# carries each package's SHA256, so authenticity still holds. (Don't curl Gitea's served
# bazzite.repo verbatim — it sets gpgcheck=1, which fails on unsigned packages.)
sudo tee /etc/yum.repos.d/punktfunk.repo >/dev/null <<'REPO'
[gitea-unom-bazzite]
name=punktfunk (unom, Bazzite)
baseurl=https://git.unom.io/api/packages/unom/rpm/bazzite
enabled=1
gpgcheck=0
repo_gpgcheck=1
gpgkey=https://git.unom.io/api/packages/unom/rpm/repository.key
REPO
# Layer the host + the web console, then reboot into the new deployment.
# (punktfunk Recommends punktfunk-web; list it explicitly so it's pulled regardless of weak-dep
# settings — the Gitea registry carries punktfunk-web, which COPR can't build.)
rpm-ostree install punktfunk punktfunk-web
systemctl reboot
```
`rpm-ostree upgrade` then tracks new builds automatically (Bazzite's auto-update timer does this
for you). For a fully baked appliance image there's also a **bootc** Containerfile that installs
the same RPMs from this registry — see `packaging/bootc/` and `packaging/rpm/README.md` in the repo.
Building from source works too (Bazzite is Fedora Atomic underneath, and its FFmpeg builds the host
fine — same steps as [Fedora KDE](/docs/fedora-kde)), but the registry is the supported path.
## Allow controller input
@@ -32,7 +59,14 @@ permission, not a client problem.)
## Configure
Point the host at the gamescope backend in `~/.config/punktfunk/host.env`:
The RPM ships a gamescope-ready config you can copy as your starting point:
```sh
mkdir -p ~/.config/punktfunk
cp /usr/share/punktfunk/host.env.bazzite ~/.config/punktfunk/host.env
```
The key settings in `~/.config/punktfunk/host.env` point the host at the gamescope backend:
```sh
PUNKTFUNK_COMPOSITOR=gamescope
@@ -51,6 +85,14 @@ Bazzite hosts are typically headless. Enable the host service and linger so it s
[Running as a Service](/docs/running-as-a-service). Because the host launches its own gamescope
session per client, you don't need a separate desktop-session unit.
```sh
systemctl --user enable --now punktfunk-host
# Web console (pairing + status) — enable it and read the auto-generated login password,
# then open http://<host-ip>:3000:
systemctl --user enable --now punktfunk-web
journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p'
```
## Good to know
- **gamescope 3.16.22 or newer is required.** Older versions can deadlock during capture. Bazzite's
+35 -9
View File
@@ -3,7 +3,8 @@ title: Clients
description: The ways to connect to a punktfunk host — the Apple app, Moonlight, or the Linux client.
---
A punktfunk host accepts two kinds of client. Pick whichever fits the device you're streaming *to*.
A punktfunk host accepts clients over its own `punktfunk/1` protocol (the Apple and Linux apps) and
over GameStream (Moonlight). Pick whichever fits the device you're streaming *to*.
## Apple app (Mac, iPhone, iPad, Apple TV)
@@ -28,24 +29,49 @@ software. See [Connect with Moonlight](/docs/moonlight).
This is the broadest-compatibility option and great for couch gaming. It doesn't use the native
protocol's FEC/encryption extensions, but for a healthy LAN that rarely matters.
## Linux reference client
## Linux desktop client (GTK4)
`punktfunk-client-rs` (in the repo) is a command-line client for the native protocol, mainly for
testing and development. It connects, streams to a file, runs the speed test, and can discover hosts:
`punktfunk-client` is the native graphical Linux client — a GTK4 / libadwaita app that speaks
`punktfunk/1` directly, with hardware decode (VAAPI → dmabuf on Intel/AMD, software fallback),
PipeWire audio, and SDL3 controllers (rumble, lightbar, DualSense touchpad/motion). Like the Apple
app it discovers hosts on your network automatically, does PIN pairing, and pins reconnects.
It ships as a real package, not just a source build:
- **Ubuntu / Debian** — `apt install punktfunk-client` from the punktfunk apt registry
(see `packaging/debian/README.md`).
- **Fedora / Bazzite** — `rpm-ostree install punktfunk-client` from the Gitea RPM registry
(see `packaging/rpm/README.md`).
- **Arch / SteamOS** — the `punktfunk-client` split package from the `PKGBUILD`
(see `packaging/arch/README.md`).
- **Steam Deck / any Flatpak distro** — the `io.unom.Punktfunk` Flatpak bundle
(see `packaging/flatpak/README.md`); this is what the Decky plugin launches.
Launch it, pick your host from the list, and stream. For scripting you can skip the host list and
connect straight away:
```sh
punktfunk-client-rs --discover # list hosts on the network
punktfunk-client-rs --connect <host>:9777 --pin <fp> # connect to one
punktfunk-client --connect <host>:9777 # skip the picker, start a session immediately
```
A full graphical Linux client (hardware decode + present) is on the [roadmap](/docs/roadmap).
## Linux reference client (headless)
`punktfunk-client-rs` (in the repo) is a command-line client for the native protocol, used for
testing, development, and latency measurement — not an everyday client. It connects, streams to a
file, runs the speed test, and can discover hosts:
```sh
punktfunk-client-rs --discover # list hosts on the network
punktfunk-client-rs --connect <host>:9777 --pin <fp> # connect to one
```
## Which should I use?
| You're streaming to… | Use |
|---|---|
| A Mac, iPhone, iPad, or Apple TV | The **Apple app** |
| Windows, Android, Steam Deck, a browser, a TV | **Moonlight** |
| Another Linux box (testing) | **`punktfunk-client-rs`** |
| A Linux desktop or laptop, or a Steam Deck | **`punktfunk-client`** (GTK4) |
| Windows, Android, a browser, a TV | **Moonlight** |
| Automated tests / latency measurement | **`punktfunk-client-rs`** (headless) |
Whichever you choose, the first connection needs a one-time [pairing](/docs/pairing).
+6 -5
View File
@@ -43,12 +43,13 @@ The client requests a bitrate; the host encodes to it. To find a good value for
## Multiple devices at once
A host can stream to several clients simultaneously — each gets its own virtual display at its own
resolution. This is the natural way to put your desktop on a laptop *and* a TV at the same time (both
see and control the same desktop).
Today the native `punktfunk/1` host (`serve --native`) streams **one session at a time** — additional
clients wait in the accept queue until the active session ends. Each session gets its own virtual
display at the client's exact resolution; concurrent native sessions are on the roadmap.
The number of simultaneous streams is bounded by your GPU's encoder. Cap it with
`--max-concurrent N` on the host command line (default 4); extra clients wait until a slot frees.
(`m3-host`, the standalone test host, has a `--max-concurrent N` knob, default 4, bounded by your
GPU's encoder — see the [Host CLI](/docs/host-cli) reference — but `serve --native` does **not** take
that flag.)
## Codec and FEC
+4 -3
View File
@@ -113,9 +113,10 @@ mDNS. It requires **PIN pairing** by default (secure on a LAN); pair once from y
## 4. Connect a client
From any [client](/docs/clients) — `punktfunk-client --discover` finds the host on the LAN. On
first connect, complete the PIN pairing (arm it from the host's web console / mgmt API, or run the
host with `--allow-pairing`). See [Clients](/docs/clients) and
[Running as a Service](/docs/running-as-a-service).
first connect, complete the PIN pairing **arm it from the host's web console / mgmt API**, which
makes the host display a 4-digit PIN to type into the client. (Pairing is required by default; pass
`serve --native --open` only if you deliberately want to disable the requirement.) See
[Clients](/docs/clients) and [Running as a Service](/docs/running-as-a-service).
## Appendix — build from source
+17 -4
View File
@@ -21,10 +21,18 @@ punktfunk-host serve --native
| `--native-port <PORT>` | Native QUIC port (default `9777`). |
| `--open` | Don't require pairing — serve any device on the network. Off by default; only for trusted single-user setups. |
| `--mgmt-bind <IP:PORT>` | Management API address (default loopback `127.0.0.1:47990`). |
| `--mgmt-token <TOKEN>` | Bearer token for the management API; required when `--mgmt-bind` isn't loopback. |
| `--mgmt-token <TOKEN>` | Override the bearer token for the management API. |
By default the host **requires pairing** — see [Pairing & Trust](/docs/pairing). Arm pairing from the
web console (or the `m3-host` flags below for a quick test).
These are the only flags `serve` accepts.
The management API is **always HTTPS with bearer-token auth**. If you don't pass `--mgmt-token`, a token
is auto-generated and persisted to `~/.config/punktfunk/mgmt-token`; `--mgmt-token` only overrides it. A
token is **required** when you bind the API off loopback with `--mgmt-bind`.
By default the host **requires pairing** — see [Pairing & Trust](/docs/pairing). On `serve --native` you
**arm pairing from the web console** (or mgmt API); the host then displays a 4-digit PIN. Pass `--open` to
turn off the mandatory-pairing default and serve any device on the network (trusted single-user setups
only). The pairing flags below are `m3-host`-only and do **not** apply to `serve`.
## `m3-host`
@@ -38,12 +46,17 @@ punktfunk-host m3-host --source virtual
| Flag | Meaning |
|---|---|
| `--port <N>` | QUIC listen port (default `9777`). |
| `--source virtual` | Use a real virtual display + NVENC (vs. `synthetic` test frames). |
| `--source synthetic` · `virtual` | `virtual` uses a real virtual display + NVENC; `synthetic` emits test frames. |
| `--seconds <N>` / `--frames <N>` | Bound each session by wall-clock seconds or frame count. |
| `--max-concurrent <N>` | Stream at most N sessions at once (default 4); overflow waits in the queue. |
| `--max-sessions <N>` | Exit after N sessions (0 = serve forever). |
| `--allow-pairing` | Accept PIN pairing; the host prints a PIN when a client pairs. |
| `--require-pairing` | Only serve paired devices (implies `--allow-pairing`). |
`--max-concurrent`, `--allow-pairing`, and `--require-pairing` are **`m3-host`-only** — `serve` does not
accept them. On `serve --native` you arm pairing from the web console instead, and concurrency is not
yet capped from the command line.
Both `serve --native` and `m3-host` advertise the host on the network so clients can discover it. List
hosts from another machine with `punktfunk-client-rs --discover`.
+54
View File
@@ -0,0 +1,54 @@
---
title: Install the Host
description: Pick your distro and install the punktfunk host from its package registry.
---
The package registries are the real distribution channel. Pick your distro, add the repo, and install
with your native package manager. Each row links to the full per-distro guide (add the repo, first-run
steps, the web console) — those are the source of truth, so this page doesn't duplicate them.
## Pick your distro
| 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) |
| **Fedora / Bazzite** | rpm-ostree | `rpm-ostree install punktfunk punktfunk-web` | [Fedora — KDE](/docs/fedora-kde) · [Bazzite](/docs/bazzite) · [packaging/rpm](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/rpm/README.md) |
| **Arch / Steam Deck** | PKGBUILD / sysext | `makepkg -si` (Arch) · sysext `.raw` (SteamOS/Deck) | [packaging/arch](https://git.unom.io/unom/punktfunk/src/branch/main/packaging/arch/README.md) |
Each registry is public — no auth, you just trust the repo's signing key. Adding the repo is a
one-time step covered in the linked guide; after that, normal `apt upgrade` / `rpm-ostree upgrade`
tracks new builds automatically.
## What the packages are
- **`punktfunk-host`** — the streaming host. Install this on your Linux + NVIDIA gaming machine.
- **`punktfunk-web`** — the browser management console (pairing + status). Recommended alongside the
host; on RPM list it explicitly (`rpm-ostree install punktfunk punktfunk-web`).
- **`punktfunk-client`** — the GTK4 desktop client, for streaming *to* a Linux box (also shipped via
apt / RPM / Arch / Flatpak). On a Steam Deck, this is the package you want.
## After installing
1. Add yourself to the `input` group (virtual gamepads need `/dev/uinput`), then re-login. The exact
command differs per distro — see your guide (`usermod -aG input "$USER"`, or `ujust
add-user-to-input-group` on Bazzite).
2. Start the host inside your desktop session:
```sh
punktfunk-host serve --native
```
3. Enable the web console and read its login password, then open `http://<host-ip>:3000`:
```sh
systemctl --user enable --now punktfunk-web
journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p'
```
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).
## Building from source
If no package exists for your platform, you can build from source — see the repository README. Source
builds are a fallback; the registries are the supported path.
+1
View File
@@ -4,6 +4,7 @@
"index",
"how-it-works",
"quickstart",
"install",
"---Host Setup---",
"requirements",
"ubuntu-gnome",
+8 -8
View File
@@ -38,13 +38,13 @@ The PIN ceremony is the other path — useful for the *first* device (before the
anything) or when you're at the client and the console isn't handy.
Pairing has to be **armed** on the host before a client can pair (so a random device can't pair
itself). Two ways:
itself). On the production host (`serve --native`), this is done from the **web console**: open the
host's management console, click to arm pairing, and the host displays a 4-digit PIN along with the
list of paired devices. This works on a headless host over the network — there is no command-line flag
to arm pairing on `serve`.
- **Web console** *(recommended)* — open the host's management console, click to arm pairing, and it
shows the PIN and the list of paired devices. This is the easiest way and works on a headless host
over the network.
- **Command line** — start the host with `--allow-pairing` (or `--require-pairing`); it prints a PIN
in its log when a client begins pairing.
(The standalone headless test host, `m3-host`, takes `--allow-pairing`/`--require-pairing` on its
command line instead; the production `serve --native` host arms pairing from the console.)
Then, on the client:
@@ -57,8 +57,8 @@ By default, the native host **requires** pairing — only devices that have pair
the right setting on a shared network: a device has to complete the PIN ceremony once before it can
connect.
If you're on a fully trusted single-user network and want to skip pairing, the host can be run open —
but requiring pairing is strongly recommended.
If you're on a fully trusted single-user network and want to skip pairing, start the host with
`serve --native --open`but requiring pairing is strongly recommended.
## Trust-on-first-use
+3 -3
View File
@@ -37,9 +37,9 @@ On the device you want to stream to:
network*. Tap 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 (or with
`--allow-pairing` on the command line) — the host displays a 4-digit PIN, you type it into the client,
and they trust each other from then on. Full details: [Pairing & Trust](/docs/pairing).
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).
## 4. Stream
+10 -6
View File
@@ -10,8 +10,11 @@ description: Common problems setting up or using a punktfunk host, and how to fi
- Host and client must be on the **same network/subnet**. Discovery uses mDNS, which doesn't cross
routed subnets or most VPNs-without-multicast. As a fallback, add the host by **IP address** in your
client.
- A firewall on the host can block it. The native protocol uses UDP port **9777** (plus the data
port); GameStream/Moonlight uses its standard ports. Allow them on the host's firewall.
- A firewall on the host can block it. The native protocol's control plane uses UDP port **9777**. The
per-session **data plane** uses an *ephemeral* UDP port negotiated at connect time (currently
random) — for a strict firewall, open a UDP range or move the data port. GameStream/Moonlight uses
TCP **47984/47989/48010** + UDP **4799848010** + ENet UDP **47999**. Allow them on the host's
firewall.
## `nvidia-smi` says it can't communicate with the driver
@@ -56,8 +59,8 @@ Then log out and back in. On other distros this is `sudo usermod -aG input $USER
## Pairing is rejected / the client can't connect
- The host **requires pairing** by default. Arm pairing (web console, or `--allow-pairing`), then
enter the PIN on the client. See [Pairing & Trust](/docs/pairing).
- The host **requires pairing** by default. Arm pairing from the web console, then enter the PIN on
the client. See [Pairing & Trust](/docs/pairing).
- If you re-installed the host, its identity changed — re-pair the client.
## Stutter, drops, or high latency
@@ -65,8 +68,9 @@ Then log out and back in. On other distros this is `sudo usermod -aG input $USER
- Lower the **bitrate**. On a busy or Wi-Fi link, the requested bitrate may be too high — the Apple
app's [speed test](/docs/configuration#bitrate) picks a safe value; with Moonlight, set it manually.
- Prefer a **wired** connection or 5 GHz Wi-Fi between host and client.
- Streaming to **many devices at once** shares the GPU encoder; cap concurrency with
`--max-concurrent`.
- Streaming to **many devices at once** shares the GPU encoder. The production host
(`serve --native`) handles one native session at a time, with extra clients queued; heavy load is
usually bitrate-bound, so lower the bitrate first.
## Still stuck?
+71 -32
View File
@@ -42,39 +42,35 @@ sudo update-initramfs -u && sudo reboot
> `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.
## 2. Dependencies
## 2. Install the host (apt)
Install the build toolchain and runtime libraries:
`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 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
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
```
Install Rust if you don't have it:
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
## 3. Build
```sh
git clone https://git.unom.io/unom/punktfunk.git && cd punktfunk
cargo build --release -p punktfunk-host
```
The host binary is at `target/release/punktfunk-host`.
## 4. Configure
The host reads its settings from `~/.config/punktfunk/host.env`. For GNOME:
`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`.
## 3. Configure
The package ships the systemd **user** unit, the `/dev/uinput` udev rule, the socket-buffer sysctl
tuning, and an example config. As the desktop user, grant gamepad access and write the GNOME config:
```sh
sudo usermod -aG input "$USER" # /dev/uinput for virtual gamepads (re-login to apply)
mkdir -p ~/.config/punktfunk
cat > ~/.config/punktfunk/host.env <<'ENV'
WAYLAND_DISPLAY=wayland-0
@@ -88,18 +84,30 @@ ENV
See the [Configuration reference](/docs/configuration) for every option.
## 5. Run
## 4. Run
From a terminal **inside your GNOME session** (so the host can reach Mutter):
Start the host as a user service from **inside your GNOME session** (so it can reach Mutter):
```sh
cargo run --release -p punktfunk-host -- serve --native
systemctl --user enable --now punktfunk-host
journalctl --user -u punktfunk-host -f # watch it come up + print its fingerprint
```
The host starts listening, prints its fingerprint, and advertises itself on the network. Now
[connect a client](/docs/clients).
The host listens on UDP `9777` (native punktfunk/1) plus the GameStream ports, and advertises itself
over mDNS. It requires **PIN pairing** by default (secure on a LAN) — arm pairing from the web
console (next step) and pair once from your [client](/docs/clients).
To run it automatically at boot — including on a **headless** machine with no monitor — see
### Web console
The console (status, paired devices, arm pairing) ships as `punktfunk-web`:
```sh
systemctl --user enable --now punktfunk-web
# read the auto-generated login password, then open http://<host-ip>:3000
journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p'
```
To run the host automatically at boot — including on a **headless** machine with no monitor — see
[Running as a Service](/docs/running-as-a-service).
## Troubleshooting
@@ -111,3 +119,34 @@ To run it automatically at boot — including on a **headless** machine with no
capture. On a headless/always-on host, disable the lock — see
[Running as a Service](/docs/running-as-a-service).
- More in [Troubleshooting](/docs/troubleshooting).
## 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`. Write `~/.config/punktfunk/host.env` as in
step 3, then run it inside your GNOME session:
```sh
cargo run --release -p punktfunk-host -- serve --native
```
+64 -14
View File
@@ -8,21 +8,42 @@ create a per-client virtual display. Needs **KWin 6.5.6 or newer**.
> New to this? Skim [Requirements](/docs/requirements) first.
## NVIDIA driver, dependencies, and build
## 1. NVIDIA driver
These steps are identical to the GNOME guide — follow **steps 13** of
[Ubuntu — GNOME](/docs/ubuntu-gnome#1-nvidia-driver):
Identical to the GNOME guide — follow **step 1** of
[Ubuntu — GNOME](/docs/ubuntu-gnome#1-nvidia-driver): install the NVIDIA driver **and** the
`libnvidia-gl-<version>` userspace, enable `nvidia-drm modeset=1`, reboot, and verify with
`nvidia-smi`.
1. Install the NVIDIA driver **and** the `libnvidia-gl-<version>` userspace; enable `nvidia-drm
modeset=1`; reboot and verify with `nvidia-smi`.
2. Install the build toolchain and runtime libraries (the same `apt` line).
3. Clone and `cargo build --release -p punktfunk-host`.
## 2. Install the host (apt)
## Configure
The host reads `~/.config/punktfunk/host.env`. For KDE Plasma:
The host is published as a `.deb` to the public Gitea apt registry — install and update with plain
`apt`. Trust the repo's signing key, add the repo, and install:
```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
```
This also pulls the web console (`punktfunk-web`) via `Recommends` (the pairing/status UI). The
desktop *client*`punktfunk-client`, for the machine you stream *to* — is a separate package, not
needed on a host. The NVIDIA driver stays out of band (step 1). Updates later are just
`sudo apt update && sudo apt upgrade`.
## 3. Configure
The package ships the systemd **user** unit, the udev rule, and the sysctl tuning. As the desktop
user, grant gamepad access and write the KDE config:
```sh
sudo usermod -aG input "$USER" # /dev/uinput for virtual gamepads (re-login to apply)
mkdir -p ~/.config/punktfunk
cat > ~/.config/punktfunk/host.env <<'ENV'
WAYLAND_DISPLAY=wayland-0
@@ -38,15 +59,26 @@ ENV
> virtual-display path is Wayland-only. See the [Configuration reference](/docs/configuration) for
> every option.
## Run
## 4. Run
From a terminal **inside your Plasma session**:
Start the host as a user service from **inside your Plasma session**:
```sh
cargo run --release -p punktfunk-host -- serve --native
systemctl --user enable --now punktfunk-host
journalctl --user -u punktfunk-host -f # watch it come up + print its fingerprint
```
The host starts listening and advertises itself on the network. Now [connect a client](/docs/clients).
The host listens on UDP `9777` (native punktfunk/1) plus the GameStream ports and advertises over
mDNS. It requires **PIN pairing** by default — arm pairing from the web console and pair once from
your [client](/docs/clients).
### Web console
```sh
systemctl --user enable --now punktfunk-web
# read the auto-generated login password, then open http://<host-ip>:3000
journalctl --user -u punktfunk-web-init | sed -n 's/.*password generated: //p'
```
To run it at boot — including fully **headless**, with KWin brought up automatically and no login —
see [Running as a Service](/docs/running-as-a-service); the headless appliance is built around KDE.
@@ -56,3 +88,21 @@ see [Running as a Service](/docs/running-as-a-service); the headless appliance i
- **KWin too old:** virtual outputs need KWin **≥ 6.5.6**. Check with `kwin_wayland --version`.
- **No picture / capture fails:** confirm you're on a Wayland session and the NVIDIA GL userspace is
installed (`libnvidia-gl-<version>`). More in [Troubleshooting](/docs/troubleshooting).
## Appendix — build from source
If the apt registry has no build for your release, compile the host yourself (no clean updates / no
packaged units). Install the build toolchain and runtime libraries — the same `apt` line as the
[GNOME build-from-source appendix](/docs/ubuntu-gnome#appendix--build-from-source) — then:
```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
```
Write `~/.config/punktfunk/host.env` as in step 3, then run it inside your Plasma session:
```sh
cargo run --release -p punktfunk-host -- serve --native
```