From f6d85f11e294d4cfdd99ec841adc5a5ac94f4fc7 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Thu, 27 Aug 2026 12:09:59 +0200 Subject: [PATCH] fix(install): the web console is named in every install line, and a host that has none gets one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .gitea/workflows/installer-smoke.yml | 20 +++++++++++ data/platforms.json | 4 +-- docs-site/content/docs/arch.mdx | 6 ++-- docs-site/content/docs/debian.mdx | 5 ++- docs-site/content/docs/install.mdx | 17 +++++---- docs-site/content/docs/ubuntu.mdx | 6 ++-- docs-site/content/docs/web-console.md | 21 ++++++----- docs-site/src/data/platforms.json | 4 +-- scripts/ci/check-docs-drift.sh | 10 +++--- scripts/install.sh | 51 ++++++++++++++++++++------- 10 files changed, 101 insertions(+), 43 deletions(-) diff --git a/.gitea/workflows/installer-smoke.yml b/.gitea/workflows/installer-smoke.yml index 2084b4b9..836b2079 100644 --- a/.gitea/workflows/installer-smoke.yml +++ b/.gitea/workflows/installer-smoke.yml @@ -39,12 +39,15 @@ jobs: - family: debian-13 image: debian:trixie prep: apt-get update -qq && apt-get install -y -qq --no-install-recommends ca-certificates curl git nodejs + rmweb: apt-get purge -y punktfunk-web - family: fedora-44 image: fedora:44 prep: dnf install -y -q curl git nodejs + rmweb: dnf remove -y punktfunk-web - family: arch image: archlinux:base prep: pacman -Sy --noconfirm --needed curl git nodejs && (pacman-key --init >/dev/null 2>&1 || true) + rmweb: pacman -Rns --noconfirm punktfunk-web container: image: ${{ matrix.image }} steps: @@ -59,8 +62,25 @@ jobs: run: | punktfunk-host --version punktfunk-host detect-conflicts + # The console is the whole management surface — pairing, approving a device, every setting. + # A host without it can be installed and still be useless, so assert it by name: the binary + # the package puts on PATH and the user unit step 6 enables. + - name: The web console is installed too + run: | + command -v punktfunk-web-server + test -f /usr/lib/systemd/user/punktfunk-web.service - name: Re-running is a no-op install run: sh scripts/install.sh --yes --no-start | grep -q 'already installed' + # The reported Fedora failure, as a test: a box that has the host but lost (or never got) + # the console must get one back from a re-run. Before the per-package check, the installer + # saw punktfunk-host on PATH, declared itself done, and left the box without a console + # while still printing the console's URL. + - name: A host without a console gets one back on re-run + run: | + ${{ matrix.rmweb }} + ! command -v punktfunk-web-server + sh scripts/install.sh --yes --no-start + command -v punktfunk-web-server - name: --uninstall takes the packages and the repo off again run: | sh scripts/install.sh --yes --uninstall diff --git a/data/platforms.json b/data/platforms.json index 59a2296e..31f385cb 100644 --- a/data/platforms.json +++ b/data/platforms.json @@ -81,7 +81,7 @@ "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" + "sudo apt install punktfunk-host punktfunk-web punktfunk-scripting" ] }, { @@ -95,7 +95,7 @@ "curl -fsS https://git.unom.io/api/packages/unom/arch/repository.key | sudo pacman-key --add -", "sudo pacman-key --lsign-key E0CA04465C99C936E0B0C6510A317015A34DDD69", "grep -q '^\\[punktfunk\\]' /etc/pacman.conf || printf '\\n[punktfunk]\\nServer = https://git.unom.io/api/packages/unom/arch/$repo/$arch\\n' | sudo tee -a /etc/pacman.conf >/dev/null", - "sudo pacman -Syu punktfunk-host" + "sudo pacman -Syu punktfunk-host punktfunk-web punktfunk-scripting" ] }, { diff --git a/docs-site/content/docs/arch.mdx b/docs-site/content/docs/arch.mdx index c779eae8..449d8126 100644 --- a/docs-site/content/docs/arch.mdx +++ b/docs-site/content/docs/arch.mdx @@ -22,9 +22,9 @@ the partial upgrade that breaks Arch boxes: -The browser console is **optional** on Arch, so name it yourself — same line, full upgrade: -`sudo pacman -Syu punktfunk-web`. (Also in the repo: `punktfunk-gamescope` for HDR off gamescope, -`punktfunk-scripting` for [plugins](/docs/plugins), `punktfunk-client` if this box is also a client.) +The browser console and the plugin runner are *optional* packages on Arch — pacman never installs +an optional dependency, so the line names them. (Also in the repo: `punktfunk-gamescope` for HDR off +gamescope, `punktfunk-client` if this box is also a client.) From then on a normal `sudo pacman -Syu` moves every Punktfunk package; restart the host afterwards (`systemctl --user restart punktfunk-host`) — or let the [console do it](/docs/updating). diff --git a/docs-site/content/docs/debian.mdx b/docs-site/content/docs/debian.mdx index 91f47076..8cc2b7e0 100644 --- a/docs-site/content/docs/debian.mdx +++ b/docs-site/content/docs/debian.mdx @@ -28,7 +28,10 @@ package needs 2.39) — [build from source](/docs/build-from-source) there, or u ## 2. Install the host The repo is public and signed — the `debian` in the URL is the package format, it's the same repo -Ubuntu uses. The browser console, `punktfunk-web`, comes along automatically: +Ubuntu uses. The line names the browser console (`punktfunk-web`) and the plugin runner +(`punktfunk-scripting`) explicitly rather than leaning on apt to pull them in: they are only +*recommended* by `punktfunk-host`, and a box with `APT::Install-Recommends "0"` would end up with +a host you cannot pair with. diff --git a/docs-site/content/docs/install.mdx b/docs-site/content/docs/install.mdx index fea9bda9..a98cde0d 100644 --- a/docs-site/content/docs/install.mdx +++ b/docs-site/content/docs/install.mdx @@ -9,10 +9,10 @@ The **host** is the program on the PC you stream *from*. It installs from Punktf repositories on Linux and from a signed installer on Windows — pick your system: - + - - + + @@ -51,10 +51,13 @@ they show (CI fails if the two drift apart). Re-running is safe. - **Already running Sunshine, Apollo or Vibeshine?** They can coexist, with one port moved — see [Switching from Sunshine](/docs/switching-from-sunshine) before you install. - **What gets installed.** `punktfunk-host` is the host; `punktfunk-web` is the browser console - (pairing, status, library — apt and RPM pull it in automatically, on Arch you name it yourself, - the Bazzite image contains it); `punktfunk-scripting` is the plugin runner that brings your - game launchers into the [library](/docs/game-library) (started for you everywhere except Arch and - source builds — `systemctl --user enable --now punktfunk-scripting` there). + (pairing, status, library); `punktfunk-scripting` is the plugin runner that brings your game + launchers into the [library](/docs/game-library) (started for you everywhere except Arch and + source builds — `systemctl --user enable --now punktfunk-scripting` there). Every install line + on these pages names all three. The host package only *recommends* the console, and a package + manager set to skip weak deps (`install_weak_deps=False`, `APT::Install-Recommends "0"`) would + otherwise leave you with a host and no way to pair with it. The Bazzite image contains all + three already. - **Stable by default.** Every guide points at the **stable** channel, which moves on `vX.Y.Z` releases. The latest `main` build is the **canary** channel — [Release Channels](/docs/channels). - **Updating and removing** are one page each: [Updating the Host](/docs/updating) (the console diff --git a/docs-site/content/docs/ubuntu.mdx b/docs-site/content/docs/ubuntu.mdx index 92277e58..bd6b5a0f 100644 --- a/docs-site/content/docs/ubuntu.mdx +++ b/docs-site/content/docs/ubuntu.mdx @@ -26,8 +26,10 @@ For **Ubuntu 26.04 or newer**, Desktop or Server, GNOME or KDE. ## 2. Install the host -The repo is public and signed; this adds it and installs the host (the browser console, -`punktfunk-web`, comes along automatically): +The repo is public and signed; this adds it and installs the host together with the browser +console (`punktfunk-web`) and the plugin runner (`punktfunk-scripting`). They are named in the +line rather than left to apt: `punktfunk-host` only *recommends* them, so a box with +`APT::Install-Recommends "0"` would end up with a host you cannot pair with. diff --git a/docs-site/content/docs/web-console.md b/docs-site/content/docs/web-console.md index 3676c460..f5819d1d 100644 --- a/docs-site/content/docs/web-console.md +++ b/docs-site/content/docs/web-console.md @@ -36,23 +36,26 @@ In practice: ## Enable the console -- **Linux packages (apt / RPM / Bazzite):** the host package (`punktfunk-host` on Ubuntu, - `punktfunk` on Fedora/Bazzite) *recommends* `punktfunk-web`, so your package manager pulls the - console in with the host (the Bazzite sysext image already contains it). Enable it as your - desktop user: +- **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://:47992 ``` -- **Arch / CachyOS (pacman):** the console is an *optional* package and pacman never installs - optional dependencies — install it from the same repo the host came from (see - [Arch Linux](/docs/arch)), then enable it as above. Use a full `-Syu`, never a bare `pacman -S`, - to avoid a partial upgrade: + **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 pacman -Syu punktfunk-web + 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 ``` diff --git a/docs-site/src/data/platforms.json b/docs-site/src/data/platforms.json index 59a2296e..31f385cb 100644 --- a/docs-site/src/data/platforms.json +++ b/docs-site/src/data/platforms.json @@ -81,7 +81,7 @@ "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" + "sudo apt install punktfunk-host punktfunk-web punktfunk-scripting" ] }, { @@ -95,7 +95,7 @@ "curl -fsS https://git.unom.io/api/packages/unom/arch/repository.key | sudo pacman-key --add -", "sudo pacman-key --lsign-key E0CA04465C99C936E0B0C6510A317015A34DDD69", "grep -q '^\\[punktfunk\\]' /etc/pacman.conf || printf '\\n[punktfunk]\\nServer = https://git.unom.io/api/packages/unom/arch/$repo/$arch\\n' | sudo tee -a /etc/pacman.conf >/dev/null", - "sudo pacman -Syu punktfunk-host" + "sudo pacman -Syu punktfunk-host punktfunk-web punktfunk-scripting" ] }, { diff --git a/scripts/ci/check-docs-drift.sh b/scripts/ci/check-docs-drift.sh index 4f4620c3..f5cbea5b 100755 --- a/scripts/ci/check-docs-drift.sh +++ b/scripts/ci/check-docs-drift.sh @@ -140,13 +140,13 @@ installer_case() { # name os-release-body expected-substring [extra args...] fail=1 ;; esac } -installer_case debian 'ID=debian\nVERSION_ID=13\n' 'sudo apt install -y punktfunk-host' -installer_case ubuntu 'ID=ubuntu\nID_LIKE=debian\nVERSION_ID=26.04\n' 'sudo apt install -y punktfunk-host' +installer_case debian 'ID=debian\nVERSION_ID=13\n' 'sudo apt install -y punktfunk-host punktfunk-web punktfunk-scripting' +installer_case ubuntu 'ID=ubuntu\nID_LIKE=debian\nVERSION_ID=26.04\n' 'sudo apt install -y punktfunk-host punktfunk-web punktfunk-scripting' installer_case mint22 'ID=linuxmint\nID_LIKE="ubuntu debian"\nVERSION_ID=22.1\n' 'cannot host' -installer_case fedora 'ID=fedora\nVERSION_ID=44\n' 'sudo dnf install -y punktfunk' +installer_case fedora 'ID=fedora\nVERSION_ID=44\n' 'sudo dnf install -y punktfunk punktfunk-web punktfunk-scripting' installer_case fedora43 'ID=fedora\nVERSION_ID=43\n' '/rpm/bazzite' -installer_case arch 'ID=arch\n' 'sudo pacman -Syu --noconfirm punktfunk-host' -installer_case cachyos 'ID=cachyos\nID_LIKE="arch"\n' 'sudo pacman -Syu --noconfirm punktfunk-host' +installer_case arch 'ID=arch\n' 'sudo pacman -Syu --noconfirm punktfunk-host punktfunk-web punktfunk-scripting' +installer_case cachyos 'ID=cachyos\nID_LIKE="arch"\n' 'sudo pacman -Syu --noconfirm punktfunk-host punktfunk-web punktfunk-scripting' installer_case bazzite 'ID=bazzite\nID_LIKE="fedora"\nVERSION_ID=43\n' 'punktfunk-sysext.sh install' installer_case nixos 'ID=nixos\n' 'docs/nixos' installer_case steamos 'ID=steamos\nID_LIKE=arch\n' 'docs/steamos-host' diff --git a/scripts/install.sh b/scripts/install.sh index 80de7d81..9019d826 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -236,10 +236,23 @@ fi # ---------------------------------------------------------------------------- 1. install # The snippets below are data/platforms.json's install lines, verbatim (stable channel); canary # and the Fedora group are edited in. check-docs-drift.sh gate 6 keeps them identical. -if command -v punktfunk-host >/dev/null 2>&1; then - say "punktfunk-host is already installed ($(punktfunk-host --version 2>/dev/null | head -1)) — skipping the install, continuing with setup" +# +# The host, the console and the plugin runner are three separate packages on every family, so "is +# the host there?" is the wrong question to skip the install on. A box that has the host but no +# console — installed by hand, from an older docs line, or by a package manager told to drop weak +# deps (dnf `install_weak_deps=False`, APT::Install-Recommends "0") — would never get one however +# often this ran, and the console is where you pair, approve a device and change every setting. +# Ask per binary instead: each family's line below names all three, and installing one that is +# already there is a no-op. +have() { command -v "$1" >/dev/null 2>&1; } +MISSING= +have punktfunk-host || MISSING="$MISSING host" +have punktfunk-web-server || MISSING="$MISSING web-console" +have punktfunk-scripting || MISSING="$MISSING plugin-runner" +if [ -z "$MISSING" ]; then + say "host, web console and plugin runner are already installed ($(punktfunk-host --version 2>/dev/null | head -1)) — skipping the install, continuing with setup" else - say "Installing the host ($CHANNEL channel)" + say "Installing:$MISSING ($CHANNEL channel)" case "$FAMILY" in apt) repo_line='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' @@ -248,7 +261,7 @@ else run 'curl -fsSL https://git.unom.io/api/packages/unom/debian/repository.key | sudo tee /etc/apt/keyrings/punktfunk.asc >/dev/null' run "$repo_line" run 'sudo apt update' - run 'sudo apt install punktfunk-host' + run 'sudo apt install punktfunk-host punktfunk-web punktfunk-scripting' ;; pacman) repo_line=$(cat <<'LINE' @@ -260,10 +273,7 @@ LINE run 'curl -fsS https://git.unom.io/api/packages/unom/arch/repository.key | sudo pacman-key --add -' run 'sudo pacman-key --lsign-key E0CA04465C99C936E0B0C6510A317015A34DDD69' run "$repo_line" - run 'sudo pacman -Syu punktfunk-host' - if ask "Install the web console and the plugin runner too (punktfunk-web, punktfunk-scripting — optional on Arch, recommended)?" y; then - run 'sudo pacman -Syu punktfunk-web punktfunk-scripting' - fi + run 'sudo pacman -Syu punktfunk-host punktfunk-web punktfunk-scripting' ;; dnf) group=$RPM_GROUP @@ -294,8 +304,12 @@ CMD esac hash -r 2>/dev/null || true if [ "$DRY" != 1 ]; then - command -v punktfunk-host >/dev/null 2>&1 || die "the install finished but punktfunk-host isn't on PATH — open a new terminal and re-run, or see $DOCS_PAGE" + have punktfunk-host || die "the install finished but punktfunk-host isn't on PATH — open a new terminal and re-run, or see $DOCS_PAGE" ok "punktfunk-host $(punktfunk-host --version 2>/dev/null | head -1) installed" + # Not fatal — the host still streams — but say it out loud here rather than let step 7 + # hand out a console URL for something that is not on the box. + if have punktfunk-web-server; then ok "the web console (punktfunk-web) is installed" + else warn "the web console (punktfunk-web) did NOT get installed — pairing, approving a device and every setting live there. Install it by hand: $DOCS_PAGE"; fi fi fi @@ -384,7 +398,11 @@ if [ "$START" = 1 ]; then else systemctl --user daemon-reload 2>/dev/null units="punktfunk-host" - systemctl --user list-unit-files punktfunk-web.service 2>/dev/null | grep -q '^punktfunk-web.service' && units="$units punktfunk-web" + if systemctl --user list-unit-files punktfunk-web.service 2>/dev/null | grep -q '^punktfunk-web.service'; then + units="$units punktfunk-web" + else + warn "no punktfunk-web.service on this box — the console is not installed, so nothing will answer on 47992 ($DOCS_PAGE)" + fi # The plugin runner fills the game library; apt/dnf/sysext start it themselves, Arch doesn't. if systemctl --user list-unit-files punktfunk-scripting.service 2>/dev/null | grep -q disabled; then units="$units punktfunk-scripting"; fi run "systemctl --user enable --now $units" @@ -421,11 +439,20 @@ if grep -qs 0x10de /sys/bus/pci/devices/*/vendor 2>/dev/null; then fi ip=$(hostname -I 2>/dev/null | awk '{print $1}') [ -n "$ip" ] || ip=$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="src") print $(i+1); exit}') +# Step 1 is the console, so it must not be printed as fact when the console isn't installed — +# that is what sent a Fedora user looking for a page nothing was serving. (--dry-run installs +# nothing by definition, so it shows the normal text.) +if have punktfunk-web-server || [ "$DRY" = 1 ]; then + step1="1. Open the web console: https://${ip:-}:47992 (the certificate is the host's own — continue past the warning) + password: sed -n 's/^PUNKTFUNK_UI_PASSWORD=//p' ~/.config/punktfunk/web-password" +else + step1="1. Install the web console — it is NOT on this box, and pairing, approving a device and + every setting live there. The install line for your distro is on $DOCS_PAGE" +fi cat <}:47992 (the certificate is the host's own — continue past the warning) - password: sed -n 's/^PUNKTFUNK_UI_PASSWORD=//p' ~/.config/punktfunk/web-password + $step1 2. Install a client on the device you stream to ($DOCS/install-client), connect, and click Approve in the console — or Pair a device for a PIN ($DOCS/pairing). 3. Stream. Ctrl+Alt+Shift+Q hands mouse and keyboard back on desktop clients. -- 2.54.0