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:
@@ -31,6 +31,23 @@ roadmap, setup guides & progress: the docs site ([`docs-site/`](docs-site) — F
|
|||||||
`bun run dev`), with the canonical [roadmap](docs-site/content/docs/roadmap.md) and
|
`bun run dev`), with the canonical [roadmap](docs-site/content/docs/roadmap.md) and
|
||||||
[status](docs-site/content/docs/status.md) there. Design notes stay in [`docs/`](docs).
|
[status](docs-site/content/docs/status.md) there. Design notes stay in [`docs/`](docs).
|
||||||
|
|
||||||
|
## Install (host)
|
||||||
|
|
||||||
|
The package registries are the real distribution channel — pick your distro and run one command.
|
||||||
|
Per-distro setup (add the repo, first-run, web console) lives in the linked READMEs.
|
||||||
|
|
||||||
|
| Distro | One-command happy path | Details |
|
||||||
|
|--------|------------------------|---------|
|
||||||
|
| **Ubuntu / Debian** (apt) | `sudo apt install punktfunk-host` *(after adding the repo)* | [`packaging/debian/README.md`](packaging/debian/README.md) |
|
||||||
|
| **Fedora / Bazzite** (rpm-ostree) | `rpm-ostree install punktfunk punktfunk-web` *(after adding the repo; or the bootc image)* | [`packaging/rpm/README.md`](packaging/rpm/README.md) |
|
||||||
|
| **Arch / Steam Deck** (PKGBUILD / sysext) | `makepkg -si` *(Arch)* · sysext `.raw` *(SteamOS/Deck)* | [`packaging/arch/README.md`](packaging/arch/README.md) |
|
||||||
|
|
||||||
|
`punktfunk-host` is the streaming host; `punktfunk-web` is the browser console (pairing + status);
|
||||||
|
`punktfunk-client` is the GTK4 desktop client (also shipped via apt/RPM/Arch/Flatpak). After install,
|
||||||
|
run `punktfunk-host serve --native` inside your desktop session, then pair from the web console.
|
||||||
|
|
||||||
|
Building from source (below) is a fallback.
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -46,7 +63,9 @@ tools/{latency-probe,loss-harness}/ measurement (plan §10)
|
|||||||
docs/{implementation-plan,roadmap,windows-host,dualsense-haptics}.md
|
docs/{implementation-plan,roadmap,windows-host,dualsense-haptics}.md
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build & test
|
## Build & test (from source)
|
||||||
|
|
||||||
|
For development, or as an install fallback where no package is available:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo build --workspace # green on Linux and macOS
|
cargo build --workspace # green on Linux and macOS
|
||||||
|
|||||||
@@ -13,10 +13,37 @@ the mode of the device you're streaming to, not the TV the box is plugged into.
|
|||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
The host installs from the punktfunk COPR repository (see `packaging/bazzite/` in the repo for the
|
The host ships as an RPM in punktfunk's **Gitea RPM registry** (public), so a Bazzite / Fedora
|
||||||
exact COPR/RPM/bootc options). You can also build from source as on
|
Atomic box layers and updates it with `rpm-ostree`. Add the repo, then layer the host plus the web
|
||||||
[Fedora KDE](/docs/fedora-kde) — Bazzite is Fedora Atomic underneath, and its FFmpeg builds the host
|
console and reboot:
|
||||||
fine.
|
|
||||||
|
```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
|
## Allow controller input
|
||||||
|
|
||||||
@@ -32,7 +59,14 @@ permission, not a client problem.)
|
|||||||
|
|
||||||
## Configure
|
## 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
|
```sh
|
||||||
PUNKTFUNK_COMPOSITOR=gamescope
|
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
|
[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.
|
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
|
## Good to know
|
||||||
|
|
||||||
- **gamescope 3.16.22 or newer is required.** Older versions can deadlock during capture. Bazzite's
|
- **gamescope 3.16.22 or newer is required.** Older versions can deadlock during capture. Bazzite's
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ title: Clients
|
|||||||
description: The ways to connect to a punktfunk host — the Apple app, Moonlight, or the Linux client.
|
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)
|
## 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
|
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.
|
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
|
`punktfunk-client` is the native graphical Linux client — a GTK4 / libadwaita app that speaks
|
||||||
testing and development. It connects, streams to a file, runs the speed test, and can discover hosts:
|
`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
|
```sh
|
||||||
punktfunk-client-rs --discover # list hosts on the network
|
punktfunk-client --connect <host>:9777 # skip the picker, start a session immediately
|
||||||
punktfunk-client-rs --connect <host>:9777 --pin <fp> # connect to one
|
|
||||||
```
|
```
|
||||||
|
|
||||||
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?
|
## Which should I use?
|
||||||
|
|
||||||
| You're streaming to… | Use |
|
| You're streaming to… | Use |
|
||||||
|---|---|
|
|---|---|
|
||||||
| A Mac, iPhone, iPad, or Apple TV | The **Apple app** |
|
| A Mac, iPhone, iPad, or Apple TV | The **Apple app** |
|
||||||
| Windows, Android, Steam Deck, a browser, a TV | **Moonlight** |
|
| A Linux desktop or laptop, or a Steam Deck | **`punktfunk-client`** (GTK4) |
|
||||||
| Another Linux box (testing) | **`punktfunk-client-rs`** |
|
| 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).
|
Whichever you choose, the first connection needs a one-time [pairing](/docs/pairing).
|
||||||
|
|||||||
@@ -43,12 +43,13 @@ The client requests a bitrate; the host encodes to it. To find a good value for
|
|||||||
|
|
||||||
## Multiple devices at once
|
## Multiple devices at once
|
||||||
|
|
||||||
A host can stream to several clients simultaneously — each gets its own virtual display at its own
|
Today the native `punktfunk/1` host (`serve --native`) streams **one session at a time** — additional
|
||||||
resolution. This is the natural way to put your desktop on a laptop *and* a TV at the same time (both
|
clients wait in the accept queue until the active session ends. Each session gets its own virtual
|
||||||
see and control the same desktop).
|
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
|
(`m3-host`, the standalone test host, has a `--max-concurrent N` knob, default 4, bounded by your
|
||||||
`--max-concurrent N` on the host command line (default 4); extra clients wait until a slot frees.
|
GPU's encoder — see the [Host CLI](/docs/host-cli) reference — but `serve --native` does **not** take
|
||||||
|
that flag.)
|
||||||
|
|
||||||
## Codec and FEC
|
## Codec and FEC
|
||||||
|
|
||||||
|
|||||||
@@ -113,9 +113,10 @@ mDNS. It requires **PIN pairing** by default (secure on a LAN); pair once from y
|
|||||||
## 4. Connect a client
|
## 4. Connect a client
|
||||||
|
|
||||||
From any [client](/docs/clients) — `punktfunk-client --discover` finds the host on the LAN. On
|
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
|
first connect, complete the PIN pairing — **arm it from the host's web console / mgmt API**, which
|
||||||
host with `--allow-pairing`). See [Clients](/docs/clients) and
|
makes the host display a 4-digit PIN to type into the client. (Pairing is required by default; pass
|
||||||
[Running as a Service](/docs/running-as-a-service).
|
`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
|
## Appendix — build from source
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,18 @@ punktfunk-host serve --native
|
|||||||
| `--native-port <PORT>` | Native QUIC port (default `9777`). |
|
| `--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. |
|
| `--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-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
|
These are the only flags `serve` accepts.
|
||||||
web console (or the `m3-host` flags below for a quick test).
|
|
||||||
|
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`
|
## `m3-host`
|
||||||
|
|
||||||
@@ -38,12 +46,17 @@ punktfunk-host m3-host --source virtual
|
|||||||
| Flag | Meaning |
|
| Flag | Meaning |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `--port <N>` | QUIC listen port (default `9777`). |
|
| `--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-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). |
|
| `--max-sessions <N>` | Exit after N sessions (0 = serve forever). |
|
||||||
| `--allow-pairing` | Accept PIN pairing; the host prints a PIN when a client pairs. |
|
| `--allow-pairing` | Accept PIN pairing; the host prints a PIN when a client pairs. |
|
||||||
| `--require-pairing` | Only serve paired devices (implies `--allow-pairing`). |
|
| `--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
|
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`.
|
hosts from another machine with `punktfunk-client-rs --discover`.
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
"index",
|
"index",
|
||||||
"how-it-works",
|
"how-it-works",
|
||||||
"quickstart",
|
"quickstart",
|
||||||
|
"install",
|
||||||
"---Host Setup---",
|
"---Host Setup---",
|
||||||
"requirements",
|
"requirements",
|
||||||
"ubuntu-gnome",
|
"ubuntu-gnome",
|
||||||
|
|||||||
@@ -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.
|
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
|
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
|
(The standalone headless test host, `m3-host`, takes `--allow-pairing`/`--require-pairing` on its
|
||||||
shows the PIN and the list of paired devices. This is the easiest way and works on a headless host
|
command line instead; the production `serve --native` host arms pairing from the console.)
|
||||||
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.
|
|
||||||
|
|
||||||
Then, on the client:
|
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
|
the right setting on a shared network: a device has to complete the PIN ceremony once before it can
|
||||||
connect.
|
connect.
|
||||||
|
|
||||||
If you're on a fully trusted single-user network and want to skip pairing, the host can be run open —
|
If you're on a fully trusted single-user network and want to skip pairing, start the host with
|
||||||
but requiring pairing is strongly recommended.
|
`serve --native --open` — but requiring pairing is strongly recommended.
|
||||||
|
|
||||||
## Trust-on-first-use
|
## Trust-on-first-use
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ On the device you want to stream to:
|
|||||||
network*. Tap it, and when prompted, **pair**.
|
network*. Tap it, and when prompted, **pair**.
|
||||||
- **Anything with Moonlight:** add the host (it should be discovered automatically), then 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
|
To pair, the host needs to show a PIN. Arm pairing from the host's web console — the host displays a
|
||||||
`--allow-pairing` on the command line) — the host displays a 4-digit PIN, you type it into the client,
|
4-digit PIN, you type it into the client, and they trust each other from then on. Pairing is required
|
||||||
and they trust each other from then on. Full details: [Pairing & Trust](/docs/pairing).
|
by default. Full details: [Pairing & Trust](/docs/pairing).
|
||||||
|
|
||||||
## 4. Stream
|
## 4. Stream
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
- 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
|
routed subnets or most VPNs-without-multicast. As a fallback, add the host by **IP address** in your
|
||||||
client.
|
client.
|
||||||
- A firewall on the host can block it. The native protocol uses UDP port **9777** (plus the data
|
- A firewall on the host can block it. The native protocol's control plane uses UDP port **9777**. The
|
||||||
port); GameStream/Moonlight uses its standard ports. Allow them on the host's firewall.
|
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 **47998–48010** + ENet UDP **47999**. Allow them on the host's
|
||||||
|
firewall.
|
||||||
|
|
||||||
## `nvidia-smi` says it can't communicate with the driver
|
## `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
|
## Pairing is rejected / the client can't connect
|
||||||
|
|
||||||
- The host **requires pairing** by default. Arm pairing (web console, or `--allow-pairing`), then
|
- The host **requires pairing** by default. Arm pairing from the web console, then enter the PIN on
|
||||||
enter the PIN on the client. See [Pairing & Trust](/docs/pairing).
|
the client. See [Pairing & Trust](/docs/pairing).
|
||||||
- If you re-installed the host, its identity changed — re-pair the client.
|
- If you re-installed the host, its identity changed — re-pair the client.
|
||||||
|
|
||||||
## Stutter, drops, or high latency
|
## 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
|
- 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.
|
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.
|
- 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
|
- Streaming to **many devices at once** shares the GPU encoder. The production host
|
||||||
`--max-concurrent`.
|
(`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?
|
## Still stuck?
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
> `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.
|
> 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
|
```sh
|
||||||
sudo apt install build-essential pkg-config cmake clang libclang-dev nasm git curl \
|
sudo install -d -m 0755 /etc/apt/keyrings
|
||||||
pipewire pipewire-pulse wireplumber libpipewire-0.3-dev libspa-0.2-dev \
|
curl -fsSL https://git.unom.io/api/packages/unom/debian/repository.key \
|
||||||
libwayland-dev wayland-protocols libxkbcommon-dev libopus-dev \
|
| sudo tee /etc/apt/keyrings/punktfunk.asc >/dev/null
|
||||||
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 \
|
echo "deb [signed-by=/etc/apt/keyrings/punktfunk.asc] https://git.unom.io/api/packages/unom/debian stable main" \
|
||||||
libnvidia-egl-wayland1 libnvidia-egl-gbm1 libei-dev
|
| 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:
|
`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
|
||||||
```sh
|
installed on a host. The NVIDIA driver is **not** a dependency — you installed it out of band in
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
step 1. Later updates are just `sudo apt update && sudo apt upgrade`.
|
||||||
```
|
|
||||||
|
## 3. Configure
|
||||||
## 3. Build
|
|
||||||
|
The package ships the systemd **user** unit, the `/dev/uinput` udev rule, the socket-buffer sysctl
|
||||||
```sh
|
tuning, and an example config. As the desktop user, grant gamepad access and write the GNOME config:
|
||||||
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:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
sudo usermod -aG input "$USER" # /dev/uinput for virtual gamepads (re-login to apply)
|
||||||
mkdir -p ~/.config/punktfunk
|
mkdir -p ~/.config/punktfunk
|
||||||
cat > ~/.config/punktfunk/host.env <<'ENV'
|
cat > ~/.config/punktfunk/host.env <<'ENV'
|
||||||
WAYLAND_DISPLAY=wayland-0
|
WAYLAND_DISPLAY=wayland-0
|
||||||
@@ -88,18 +84,30 @@ ENV
|
|||||||
|
|
||||||
See the [Configuration reference](/docs/configuration) for every option.
|
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
|
```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
|
The host listens on UDP `9777` (native punktfunk/1) plus the GameStream ports, and advertises itself
|
||||||
[connect a client](/docs/clients).
|
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).
|
[Running as a Service](/docs/running-as-a-service).
|
||||||
|
|
||||||
## Troubleshooting
|
## 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
|
capture. On a headless/always-on host, disable the lock — see
|
||||||
[Running as a Service](/docs/running-as-a-service).
|
[Running as a Service](/docs/running-as-a-service).
|
||||||
- More in [Troubleshooting](/docs/troubleshooting).
|
- 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
|
||||||
|
```
|
||||||
|
|||||||
@@ -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.
|
> 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 1–3** of
|
Identical to the GNOME guide — follow **step 1** of
|
||||||
[Ubuntu — GNOME](/docs/ubuntu-gnome#1-nvidia-driver):
|
[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
|
## 2. Install the host (apt)
|
||||||
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`.
|
|
||||||
|
|
||||||
## Configure
|
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:
|
||||||
The host reads `~/.config/punktfunk/host.env`. For KDE Plasma:
|
|
||||||
|
|
||||||
```sh
|
```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
|
mkdir -p ~/.config/punktfunk
|
||||||
cat > ~/.config/punktfunk/host.env <<'ENV'
|
cat > ~/.config/punktfunk/host.env <<'ENV'
|
||||||
WAYLAND_DISPLAY=wayland-0
|
WAYLAND_DISPLAY=wayland-0
|
||||||
@@ -38,15 +59,26 @@ ENV
|
|||||||
> virtual-display path is Wayland-only. See the [Configuration reference](/docs/configuration) for
|
> virtual-display path is Wayland-only. See the [Configuration reference](/docs/configuration) for
|
||||||
> every option.
|
> 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
|
```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 —
|
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.
|
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`.
|
- **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
|
- **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).
|
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
|
||||||
|
```
|
||||||
|
|||||||
@@ -95,6 +95,46 @@ launches it (`punktfunk-client --connect host:port`) — gamescope composites it
|
|||||||
The client needs no `/dev/uinput` or compositor-spawning rights (it captures input and decodes),
|
The client needs no `/dev/uinput` or compositor-spawning rights (it captures input and decodes),
|
||||||
so it's a much lighter sysext than the host.
|
so it's a much lighter sysext than the host.
|
||||||
|
|
||||||
|
## Firewall
|
||||||
|
|
||||||
|
If the host box runs a firewall, open the ports it listens on. The **native `punktfunk/1`** plane:
|
||||||
|
|
||||||
|
- **QUIC control plane: UDP 9777** (`serve --native --native-port N` to change).
|
||||||
|
- **Data plane: an *ephemeral* UDP port** — negotiated per session, so there is no fixed port to
|
||||||
|
open. For a restrictive firewall you'd need to allow a UDP range (the repo does not pin one).
|
||||||
|
|
||||||
|
And the **GameStream / Moonlight** ports (fixed):
|
||||||
|
|
||||||
|
| Port | Proto | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| 47984 | TCP | HTTPS nvhttp (paired, mutual-TLS) |
|
||||||
|
| 47989 | TCP | HTTP nvhttp (`/serverinfo`, `/pair` PIN flow) |
|
||||||
|
| 48010 | TCP | RTSP handshake |
|
||||||
|
| 47998–48010 | UDP | Video RTP (+ FEC), ENet control (47999), audio (48000) |
|
||||||
|
| 5353 | UDP | mDNS auto-discovery |
|
||||||
|
|
||||||
|
The mgmt API (TCP 47990) binds to loopback by default — leave it closed unless you move it off
|
||||||
|
loopback with `--mgmt-bind IP:PORT` (which then requires `--mgmt-token`).
|
||||||
|
|
||||||
|
With `ufw`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo ufw allow 9777/udp # punktfunk/1 control plane
|
||||||
|
sudo ufw allow 47984/tcp && sudo ufw allow 47989/tcp && sudo ufw allow 48010/tcp
|
||||||
|
sudo ufw allow 47998:48010/udp
|
||||||
|
sudo ufw allow 5353/udp
|
||||||
|
# plus the ephemeral punktfunk/1 data port — open a UDP range you reserve for it.
|
||||||
|
```
|
||||||
|
|
||||||
|
With raw `nftables` (add to your `inet filter input` chain):
|
||||||
|
|
||||||
|
```
|
||||||
|
udp dport 9777 accept # punktfunk/1 control plane
|
||||||
|
tcp dport { 47984, 47989, 48010 } accept
|
||||||
|
udp dport { 47998-48010, 5353 } accept
|
||||||
|
# plus the ephemeral punktfunk/1 data port (a reserved UDP range).
|
||||||
|
```
|
||||||
|
|
||||||
## Files
|
## Files
|
||||||
- `PKGBUILD` — split package: `punktfunk-host` + `punktfunk-client` (builds the working tree via
|
- `PKGBUILD` — split package: `punktfunk-host` + `punktfunk-client` (builds the working tree via
|
||||||
`PF_SRCDIR`, or a git tag for AUR).
|
`PF_SRCDIR`, or a git tag for AUR).
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# bootc / OCI image layer that bakes punktfunk into a Bazzite-based atomic image.
|
# bootc / OCI image layer that bakes punktfunk into a Bazzite-based atomic image.
|
||||||
#
|
#
|
||||||
# Bazzite is already a bootc image (Fedora Atomic + gamescope + PipeWire + the NVIDIA
|
# Bazzite is already a bootc image (Fedora Atomic + gamescope + PipeWire + the NVIDIA
|
||||||
# stack), so we layer punktfunk on top: enable RPM Fusion (for the NVENC ffmpeg) and our
|
# stack), so we layer punktfunk on top: enable RPM Fusion (for the NVENC ffmpeg) and unom's
|
||||||
# COPR, install the package, and pre-enable the udev rule. Build + push this image, then
|
# Gitea RPM registry (NOT COPR — only the registry carries the punktfunk-web subpackage),
|
||||||
|
# install the packages, and pre-enable the udev rule. Build + push this image, then
|
||||||
# `bootc switch` (or rebase) a Bazzite host onto it for an image-based, atomic install —
|
# `bootc switch` (or rebase) a Bazzite host onto it for an image-based, atomic install —
|
||||||
# no per-host `rpm-ostree install` drift.
|
# no per-host `rpm-ostree install` drift.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ once in the COPR web UI (or with `copr-cli`):
|
|||||||
- Source build method: `rpkg` (or `make_srpm`)
|
- Source build method: `rpkg` (or `make_srpm`)
|
||||||
|
|
||||||
**Project settings**
|
**Project settings**
|
||||||
- Chroots: `fedora-41-x86_64`, `fedora-42-x86_64` (match your Bazzite Fedora base;
|
- Chroots: `fedora-43-x86_64`, `fedora-44-x86_64` (match your Bazzite Fedora base;
|
||||||
`rpm -E %fedora` on the host tells you which). Add `aarch64` if needed.
|
`rpm -E %fedora` on the host tells you which). Add `aarch64` if needed.
|
||||||
- External repositories (so `ffmpeg-devel` resolves at build time):
|
- External repositories (so `ffmpeg-devel` resolves at build time):
|
||||||
`https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$releasever.noarch.rpm`
|
`https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$releasever.noarch.rpm`
|
||||||
@@ -22,7 +22,7 @@ once in the COPR web UI (or with `copr-cli`):
|
|||||||
`copr-cli` equivalent:
|
`copr-cli` equivalent:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
copr-cli create punktfunk --chroot fedora-42-x86_64 \
|
copr-cli create punktfunk --chroot fedora-44-x86_64 \
|
||||||
--repo 'https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$releasever.noarch.rpm' \
|
--repo 'https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$releasever.noarch.rpm' \
|
||||||
--repo 'https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$releasever.noarch.rpm'
|
--repo 'https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$releasever.noarch.rpm'
|
||||||
copr-cli buildscm punktfunk \
|
copr-cli buildscm punktfunk \
|
||||||
|
|||||||
@@ -2,8 +2,16 @@
|
|||||||
|
|
||||||
`punktfunk-host` is published as a `.deb` to **Gitea's Debian package registry** in the public
|
`punktfunk-host` is published as a `.deb` to **Gitea's Debian package registry** in the public
|
||||||
`unom` org, so the Ubuntu hosts update with plain `apt`. CI (`.gitea/workflows/deb.yml`) builds
|
`unom` org, so the Ubuntu hosts update with plain `apt`. CI (`.gitea/workflows/deb.yml`) builds
|
||||||
and publishes on every push to `main` (a rolling `0.0.1~ciN.<sha>` build) and on `v*` tags
|
and publishes on every push to `main` (a rolling `0.2.0~ciN.g<sha>` build) and on `host-v*` tags
|
||||||
(a clean `X.Y.Z`).
|
(a clean `X.Y.Z`) — the rolling builds outrank the stray `0.1.1`, so plain `apt upgrade` always
|
||||||
|
gets the latest (no version pin needed).
|
||||||
|
|
||||||
|
The same workflow also publishes **`punktfunk-web`** (the browser management console — pairing +
|
||||||
|
status) and **`punktfunk-client`** (the GTK4 couch/Deck client). `punktfunk-host` **Recommends**
|
||||||
|
`punktfunk-web`, so a default `apt install punktfunk-host` pulls the console too (alongside the
|
||||||
|
udev/sysctl bits) unless you've disabled weak deps; `punktfunk-client` is independent — install it
|
||||||
|
on the box you stream *to*. (`punktfunk-client-rs` is the headless reference/test tool, not packaged
|
||||||
|
here.)
|
||||||
|
|
||||||
Package layout mirrors the Fedora RPM (`../rpm/punktfunk.spec`): the host binary, the `/dev/uinput`
|
Package layout mirrors the Fedora RPM (`../rpm/punktfunk.spec`): the host binary, the `/dev/uinput`
|
||||||
udev rule, the systemd **user** unit, headless session helpers, the example config, and the OpenAPI
|
udev rule, the systemd **user** unit, headless session helpers, the example config, and the OpenAPI
|
||||||
@@ -35,6 +43,49 @@ sudo usermod -aG input "$USER" # virtual gamepads (re-login to take eff
|
|||||||
mkdir -p ~/.config/punktfunk
|
mkdir -p ~/.config/punktfunk
|
||||||
cp /usr/share/punktfunk-host/host.env.example ~/.config/punktfunk/host.env # then edit
|
cp /usr/share/punktfunk-host/host.env.example ~/.config/punktfunk/host.env # then edit
|
||||||
systemctl --user enable --now punktfunk-host
|
systemctl --user enable --now punktfunk-host
|
||||||
|
# Web console — 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'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Firewall
|
||||||
|
|
||||||
|
Open the ports the host listens on. The **native `punktfunk/1`** plane:
|
||||||
|
|
||||||
|
- **QUIC control plane: UDP 9777** (`serve --native --native-port N` to change).
|
||||||
|
- **Data plane: an *ephemeral* UDP port** — negotiated per session, so there is no fixed port to
|
||||||
|
open. For a restrictive firewall you'd need to allow a UDP range (the repo does not pin one).
|
||||||
|
|
||||||
|
And the **GameStream / Moonlight** ports (fixed):
|
||||||
|
|
||||||
|
| Port | Proto | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| 47984 | TCP | HTTPS nvhttp (paired, mutual-TLS) |
|
||||||
|
| 47989 | TCP | HTTP nvhttp (`/serverinfo`, `/pair` PIN flow) |
|
||||||
|
| 48010 | TCP | RTSP handshake |
|
||||||
|
| 47998–48010 | UDP | Video RTP (+ FEC), ENet control (47999), audio (48000) |
|
||||||
|
| 5353 | UDP | mDNS auto-discovery |
|
||||||
|
|
||||||
|
The mgmt API (TCP 47990) binds to loopback by default — leave it closed unless you move it off
|
||||||
|
loopback with `--mgmt-bind IP:PORT` (which then requires `--mgmt-token`).
|
||||||
|
|
||||||
|
With `ufw`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo ufw allow 9777/udp # punktfunk/1 control plane
|
||||||
|
sudo ufw allow 47984/tcp && sudo ufw allow 47989/tcp && sudo ufw allow 48010/tcp
|
||||||
|
sudo ufw allow 47998:48010/udp
|
||||||
|
sudo ufw allow 5353/udp
|
||||||
|
# plus the ephemeral punktfunk/1 data port — open a UDP range you reserve for it.
|
||||||
|
```
|
||||||
|
|
||||||
|
With raw `nftables` (add to your `inet filter input` chain):
|
||||||
|
|
||||||
|
```
|
||||||
|
udp dport 9777 accept # punktfunk/1 control plane
|
||||||
|
tcp dport { 47984, 47989, 48010 } accept
|
||||||
|
udp dport { 47998-48010, 5353 } accept
|
||||||
|
# plus the ephemeral punktfunk/1 data port (a reserved UDP range).
|
||||||
```
|
```
|
||||||
|
|
||||||
## Updates
|
## Updates
|
||||||
|
|||||||
Reference in New Issue
Block a user