ci / bun-nix (pull_request) Successful in 24s
ci / docs-drift (pull_request) Successful in 25s
ci / docs-site (pull_request) Successful in 57s
ci / web (pull_request) Successful in 1m1s
installer-smoke / smoke (arch) (pull_request) Successful in 49s
ci / rust-arm64 (pull_request) Successful in 1m27s
apple / swift (pull_request) Successful in 2m6s
apple / distribute (pull_request) Skipped
apple / screenshots (pull_request) Skipped
installer-smoke / smoke (fedora-44) (pull_request) Successful in 2m21s
installer-smoke / smoke (debian-13) (pull_request) Successful in 3m19s
android / android (pull_request) Successful in 5m15s
ci / rust (pull_request) Successful in 6m10s
Reported from the field: the guided installer (scripts/install.sh) left a Fedora box with a host
and no web console — and then printed the console's URL anyway. Reproduced with the real script
against a faked Fedora 44 os-release: with `punktfunk-host` on PATH the installer prints "already
installed — skipping the install" and never runs its dnf line, so `punktfunk-web` is never added.
The console is where you pair, approve a device and change every setting, so that box can stream
nothing and offers no way to fix it.
The registry was never the problem: `punktfunk-web` is present in the fedora-44 and bazzite RPM
groups, the debian repo and the arch repo (checked all four). The install step was gated on ONE
binary while installing THREE packages.
* scripts/install.sh asks per package (host / punktfunk-web-server / punktfunk-scripting) instead
of skipping everything the moment the host binary exists. A box that got the host by hand, from
an older docs line, or from a package manager set to drop weak deps now gets its console on a
re-run. Installing a package that is already there is a no-op, so re-running stays safe.
* The install lines NAME the console on every family. apt relied on `Recommends: punktfunk-web`
and pacman on an optdepend, both of which vanish under `APT::Install-Recommends "0"` /
`install_weak_deps=False` / plain pacman. dnf already named it. The packages keep their weak
deps — a hard Requires would break the COPR build, which has no bun and ships no console — but
no documented path leans on them any more.
* The installer stops lying when the console is absent: step 6 warns instead of silently dropping
punktfunk-web from the units it enables, and the closing banner offers the install line rather
than a URL nothing serves.
Verified unchanged on the channels that were already right: the Bazzite sysext bakes in web +
scripting, the NixOS module defaults `web.enable` to `host.enable`, the SteamOS script defaults
`WITH_WEB=1`, and the Windows installer bundles the console unconditionally behind a payload guard
added after 0.22.1/0.22.2 shipped without one. COPR is the documented exception (no bun in mock).
The gates that let this ship:
* check-docs-drift.sh gate 7 asserted the install line only as far as the host package name, so
a line that dropped the console still passed. It now names all three per family.
* installer-smoke.yml asserted `punktfunk-host --version` and nothing about the console. It now
asserts the binary and the user unit per family, and carries the reported failure as a test:
remove punktfunk-web, re-run the installer, require it back.
data/platforms.json is the source for both the docs and the installer, so the per-distro pages,
the install landing page and the web-console page were updated with it — including a "no console on
a box that has the host?" recovery block for anyone already in this state.
142 lines
7.5 KiB
Markdown
142 lines
7.5 KiB
Markdown
---
|
|
title: The Web Console
|
|
description: Enable the Punktfunk browser console, read or change its login password, arm PIN pairing, and what every page in it does.
|
|
---
|
|
|
|
The web console is the browser UI for a Punktfunk host — live status, pairing, display policy, the
|
|
game library, logs, plugins and host updates. It ships as the **`punktfunk-web`** systemd user unit
|
|
on Linux, runs under the **Punktfunk Host service** on Windows, and serves on **`https://<host-ip>:47992`**
|
|
(HTTPS with the host's own self-signed identity cert — your browser warns once; trust it and
|
|
continue). It's the surface you expose on the LAN to administer the host; the host's own management
|
|
API (47990) keeps every admin action loopback-only and off-loopback serves only read-only status and
|
|
game-library browsing to paired clients.
|
|
|
|
> 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.
|
|
|
|
## Two ports, not one
|
|
|
|
The console also listens on **TCP 47993**, where plugin interfaces are served — same host, same
|
|
certificate, **different port**.
|
|
|
|
That is a deliberate boundary. A plugin's interface is third-party code; on the console's own port
|
|
the browser would let it act as you, with your logged-in session, against every admin action the
|
|
console can reach. A different port is a different *origin*, so the browser keeps the two apart —
|
|
but the same *site*, so your login still carries over.
|
|
|
|
In practice:
|
|
|
|
- **Open 47993 alongside 47992** on the host's firewall if you browse the console from another
|
|
device. The packaged firewall profiles already list both.
|
|
- **Trust the certificate twice.** Browsers store a self-signed certificate exception *per port*.
|
|
The first time you open a plugin, the console notices it can't reach 47993 yet and offers a link
|
|
to open it in a tab — accept the warning there once and it works from then on.
|
|
- If a plugin's page is an empty panel, see
|
|
[A plugin's interface doesn't load](/docs/troubleshooting#a-plugins-interface-doesnt-load).
|
|
|
|
## Enable the console
|
|
|
|
- **Linux packages (apt / RPM / Arch / Bazzite):** `punktfunk-web` is its own package, and the
|
|
install line on every distro page names it (the Bazzite sysext image already contains it).
|
|
Enable it as your desktop user:
|
|
|
|
```sh
|
|
systemctl --user enable --now punktfunk-web
|
|
# then browse to https://<host-ip>:47992
|
|
```
|
|
|
|
**No console on a box that has the host?** That is the one way this goes wrong: the host package
|
|
only *recommends* the console on apt and RPM, and lists it as an *optional* dependency on Arch
|
|
(pacman never installs those). So a host put on by hand, or by a package manager configured to
|
|
skip weak dependencies (`install_weak_deps=False` in `/etc/dnf/dnf.conf`,
|
|
`APT::Install-Recommends "0"`), has no console. Install it from the same repo the host came
|
|
from — on Arch as a full `-Syu`, never a bare `pacman -S`, to avoid a partial upgrade:
|
|
|
|
```sh
|
|
sudo dnf install punktfunk-web # Fedora
|
|
sudo apt install punktfunk-web # Debian / Ubuntu
|
|
sudo pacman -Syu punktfunk-web # Arch / CachyOS
|
|
systemctl --user enable --now punktfunk-web
|
|
```
|
|
|
|
- **Windows host:** the installer sets up the console and its runtime; the Punktfunk Host service
|
|
runs it and brings it back if it ever stops. Nothing to enable — open `https://<this-PC>:47992`.
|
|
|
|
- **SteamOS host:** the install script builds and starts the console as a user service and prints
|
|
the URL when it finishes.
|
|
|
|
## Login password
|
|
|
|
The console is password-protected; where the 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
|
|
from the init service's journal or 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=<your-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 Punktfunk Host service from an **elevated** PowerShell:
|
|
|
|
```powershell
|
|
notepad "$env:ProgramData\punktfunk\web-password" # set PUNKTFUNK_UI_PASSWORD=<your-password>
|
|
punktfunk-host service restart
|
|
```
|
|
|
|
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, log in to
|
|
the console, open **Pairing** in the sidebar and click **Pair a device**. The host shows a one-time
|
|
4-digit PIN — enter it on your [client](/docs/clients). If the device already tried to connect it
|
|
appears under **Waiting for approval** instead; approving it pairs it immediately, no PIN needed.
|
|
[Pairing & Trust](/docs/pairing) has the full trust model and how to approve or remove devices later.
|
|
|
|
## What's in it
|
|
|
|
Nine destinations in the sidebar (a **More** tab on a phone holds the last five):
|
|
|
|

|
|
|
|
- **Dashboard** — the live status above: what's streaming, which games run, how many clients are
|
|
paired. Buttons stop a session or ask the encoder for a fresh keyframe.
|
|
- **Host** — this host's identity (hostname, OS, local IP, version, unique id), the codecs it
|
|
advertises, its ports, the **Updates** card (see [Updating the Host](/docs/updating)), the
|
|
**GPUs** card — Automatic, or prefer one GPU for capture and encode, applied to the next session
|
|
— and the compositor backends it found.
|
|
- **Virtual displays** — the policy for the display each session gets, and the Streamed screen
|
|
picker. See [Virtual displays](/docs/virtual-displays).
|
|
- **Library** — the games every client sees: turn a launcher source on or off, add or edit a custom
|
|
title with its own art and launch command. See [Your game library](/docs/game-library).
|
|
- **Performance** — arm a capture, run a session, stop it, and read the recording back as
|
|
per-stage latency, throughput and health graphs.
|
|
- **Logs** — the host's recent log stream *and your plugins'*: follow it live, filter by level or
|
|
producer, search it, and download or share it for a bug report. Plugin lines are tagged
|
|
`plugin:<name>` and the **Host / Plugins** switch isolates either side.
|
|
- **Pairing** — arm a PIN, approve or deny devices waiting for approval, and unpair a device. A
|
|
second PIN box for [Moonlight/GameStream](/docs/moonlight) clients appears only when this host
|
|
runs the GameStream plane.
|
|
- **Plugins** — the plugin store's **Browse**, **Installed** and **Sources** tabs plus the plugin
|
|
runner switch; an installed plugin with a UI gets its own entry below. See
|
|
[Plugins](/docs/plugins).
|
|
- **Settings** — the console's language, and **Sign out**.
|