e27718b406
apple / swift (push) Successful in 1m10s
apple / screenshots (push) Successful in 5m45s
android / android (push) Successful in 4m2s
arch / build-publish (push) Successful in 5m37s
ci / web (push) Successful in 1m4s
ci / docs-site (push) Successful in 1m9s
ci / rust (push) Successful in 4m39s
deb / build-publish (push) Successful in 2m56s
decky / build-publish (push) Successful in 14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
ci / bench (push) Successful in 4m41s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 10m8s
docker / deploy-docs (push) Successful in 6s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m54s
Mirror the Arch firewalld service definitions into the RPM spec and the Debian
host package so every Linux packager installs them, and move the two XML files
to the shared packaging/linux/ home (alongside the .desktop files both the
PKGBUILD and deb scripts already source there) so there's one source of truth
instead of three drifting copies.
- rpm: install punktfunk-{gamestream,native}.xml to /usr/lib/firewalld/services/,
list them in %files host, and print the firewalld enable command in %post
(gated on firewall-cmd). Fedora/RHEL run firewalld by default, so this is where
it matters most; Bazzite inherits it via the sysext built from the package /usr.
- deb: install both XMLs in build-deb.sh and add the same firewalld-gated hint to
the postinst. Debian/Ubuntu ship no active firewall, so it's a no-op unless the
admin runs firewalld.
- PKGBUILD + arch README updated to the packaging/linux/ path.
- Firewall docs (bazzite README now leads with --add-service; debian README gains
a firewalld block) point at the shipped services; XML comments made
distro-neutral. Never auto-enabled — packages don't touch the admin's firewall.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
200 lines
13 KiB
Bash
200 lines
13 KiB
Bash
# Maintainer: unom <noreply@anthropic.com>
|
|
#
|
|
# Arch Linux / SteamOS split package: punktfunk-host (the gaming-rig HOST, NVENC) and
|
|
# punktfunk-client (the native GTK4/libadwaita Linux CLIENT). Mirrors the rpm subpackages
|
|
# (packaging/rpm/punktfunk.spec) and the two deb build scripts. On a Steam Deck you want
|
|
# `punktfunk-client` (it's what the Decky plugin launches); on a gaming rig, `punktfunk-host`.
|
|
#
|
|
# Two build modes:
|
|
# - AUR / standalone: makepkg in this dir (fetches the git tag below).
|
|
# - In-tree / CI: PF_SRCDIR=$(git rev-parse --show-toplevel) makepkg --holdver
|
|
# (builds the working tree instead of the tagged source — see build()).
|
|
#
|
|
# Host encode: NVENC on NVIDIA (nvidia-utils), VAAPI on AMD/Intel (mesa) — PUNKTFUNK_ENCODER=auto
|
|
# picks per GPU. The CLIENT decodes via VAAPI (AMD/Intel, incl. the Deck) with a software
|
|
# fallback, so it works everywhere. See README.md.
|
|
pkgbase=punktfunk
|
|
# punktfunk-web (the browser console) is OPT-IN: building it needs `bun` (AUR-only as bun-bin on
|
|
# stock Arch/SteamOS), so a default makepkg builds only host+client with no JS tooling — mirroring
|
|
# the RPM spec's `%bcond_with web` (off by default). Set PF_WITH_WEB=1 to also build punktfunk-web
|
|
# (appended to pkgname + bun to makedepends below).
|
|
pkgname=('punktfunk-host' 'punktfunk-client')
|
|
# CI (.gitea/workflows/arch.yml) drives the version: stable tags -> X.Y.Z-1, main pushes ->
|
|
# X.Y.Z-0.<run#> in the separate punktfunk-canary repo (mirrors the RPM's 0.ciN release; pkgrel
|
|
# allows only digits+dots, so the run number carries the monotonic ordering).
|
|
pkgver="${PF_PKGVER:-0.7.0}"
|
|
pkgrel="${PF_PKGREL:-1}"
|
|
arch=('x86_64')
|
|
url="https://git.unom.io/unom/punktfunk"
|
|
license=('MIT OR Apache-2.0')
|
|
# !lto: makepkg's `lto` option injects -flto=auto into CFLAGS; aws-lc-sys (rustls' crypto)
|
|
# compiles its C with those flags and GCC LTO bitcode objects are unreadable by rust's lld
|
|
# linker -> "undefined symbol: aws_lc_*" at link (reproduced 2026-07-04, Arch + rust 1.90).
|
|
# !debug: skip the -debug split package (debuginfo bloat, not shipped).
|
|
options=('!lto' '!debug')
|
|
|
|
# All build deps for both crates (Arch runtime packages ship their own headers, so these cover
|
|
# build + link). aws-lc/ring need clang+cmake; nasm is for asm.
|
|
makedepends=('rust' 'cargo' 'clang' 'cmake' 'nasm' 'pkgconf' 'git'
|
|
'gtk4' 'libadwaita' 'sdl3' 'ffmpeg' 'pipewire' 'wayland' 'libxkbcommon' 'opus' 'libei')
|
|
|
|
# Opt-in punktfunk-web: only then is bun (the build tool AND the vendored runtime) required.
|
|
if [ "${PF_WITH_WEB:-0}" = 1 ]; then
|
|
pkgname+=('punktfunk-web')
|
|
makedepends+=('bun') # `bun-bin` from the AUR if bun isn't in your configured repos
|
|
fi
|
|
|
|
# AUR source (a tagged release). For an in-tree CI build, set PF_SRCDIR to the repo root —
|
|
# build() uses it instead AND the fetch is skipped entirely (a canary pkgver has no tag to
|
|
# clone, and CI already has the checkout).
|
|
if [ -z "${PF_SRCDIR:-}" ]; then
|
|
source=("git+https://git.unom.io/unom/punktfunk.git#tag=v${pkgver}")
|
|
sha256sums=('SKIP')
|
|
else
|
|
source=()
|
|
sha256sums=()
|
|
fi
|
|
|
|
_repo() { printf '%s' "${PF_SRCDIR:-$srcdir/punktfunk}"; }
|
|
|
|
build() {
|
|
cd "$(_repo)"
|
|
export RUSTUP_TOOLCHAIN=stable CARGO_TARGET_DIR="$srcdir/target"
|
|
export PUNKTFUNK_BUILD_VERSION="${pkgver}-${pkgrel}" # stamp --version / mgmt /health (build.rs)
|
|
# The host's zero-copy FFI link-needs libcuda at build time; nvidia-utils provides it on an
|
|
# NVIDIA builder. On a GPU-less builder symlink the CUDA stub into the link path first (same
|
|
# caveat the RPM documents): ln -s "$(find / -name libcuda.so -path '*stubs*'|head -1)" /usr/lib/
|
|
cargo build --release --locked -p punktfunk-host -p punktfunk-client-linux -p punktfunk-tray
|
|
# Management web console (opt-in): the Nitro `bun`-preset .output bundle (Bun.serve TLS),
|
|
# built AND run with bun.
|
|
if [ "${PF_WITH_WEB:-0}" = 1 ]; then
|
|
( cd web && bun install --frozen-lockfile && bun run build )
|
|
fi
|
|
}
|
|
|
|
package_punktfunk-host() {
|
|
pkgdesc="Low-latency desktop/game streaming HOST (Moonlight-compatible + punktfunk/1)"
|
|
# NVENC + GPU EGL/CUDA come from the NVIDIA driver (nvidia-utils) — kept an optdepend, never a
|
|
# hard dep, exactly as the RPM (__requires_exclude libcuda) and deb (shlibdeps filter) do.
|
|
depends=('ffmpeg' 'pipewire' 'pipewire-pulse' 'wireplumber' 'opus' 'libei'
|
|
'mesa' 'libglvnd' 'libxkbcommon' 'wayland')
|
|
optdepends=('nvidia-utils: NVENC hardware encode + GPU EGL/CUDA zero-copy (REQUIRED to encode on NVIDIA)'
|
|
'gamescope: per-session nested compositor backend (no desktop login needed) — needs >=3.16.22'
|
|
'kwin: stream a KDE Plasma desktop (kwin VirtualDisplay backend)'
|
|
'mutter: stream a GNOME desktop (Mutter RecordVirtual backend)'
|
|
'sway: stream a wlroots desktop (Sway VirtualDisplay backend)'
|
|
'xdg-desktop-portal-kde: portal for the headless KDE session helper'
|
|
'xdg-desktop-portal-wlr: portal for the headless Sway session helper'
|
|
'punktfunk-web: browser management console (device pairing + status)')
|
|
install=punktfunk-host.install
|
|
# User-editable config: the headless game-mode drop-in (see below) — don't clobber local edits.
|
|
backup=('etc/gamescope-session-plus/sessions.d/steam')
|
|
local R; R="$(_repo)"; local T="$srcdir/target/release"
|
|
|
|
install -Dm0755 "$T/punktfunk-host" "$pkgdir/usr/bin/punktfunk-host"
|
|
# /dev/uinput + /dev/uhid -> input group (virtual gamepads + DualSense UHID)
|
|
install -Dm0644 "$R/scripts/60-punktfunk.rules" "$pkgdir/usr/lib/udev/rules.d/60-punktfunk.rules"
|
|
# 32 MB UDP socket buffers (send-side headroom at high bitrate)
|
|
install -Dm0644 "$R/scripts/99-punktfunk-net.conf" "$pkgdir/usr/lib/sysctl.d/99-punktfunk-net.conf"
|
|
# systemd USER units (the host runs in the graphical session, not as root); repoint ExecStart.
|
|
install -Dm0644 "$R/scripts/punktfunk-host.service" "$pkgdir/usr/lib/systemd/user/punktfunk-host.service"
|
|
sed -i 's#%h/punktfunk/target/release/punktfunk-host#/usr/bin/punktfunk-host#' \
|
|
"$pkgdir/usr/lib/systemd/user/punktfunk-host.service"
|
|
install -Dm0644 "$R/scripts/punktfunk-kde-session.service" "$pkgdir/usr/lib/systemd/user/punktfunk-kde-session.service"
|
|
sed -i 's#%h/punktfunk/scripts/headless/run-headless-kde.sh#/usr/share/punktfunk/headless/run-headless-kde.sh#' \
|
|
"$pkgdir/usr/lib/systemd/user/punktfunk-kde-session.service"
|
|
# KWin Desktop-mode authorization: non-launcher .desktop whose X-KDE-Wayland-Interfaces lets the
|
|
# host bind KWin's restricted zkde_screencast (virtual output) + fake_input globals on an
|
|
# interactive Plasma session. Must ship with the host (KWin caches the per-exe grant on first
|
|
# connect). See the file's header comment.
|
|
install -Dm0644 "$R/packaging/linux/io.unom.Punktfunk.Host.desktop" \
|
|
"$pkgdir/usr/share/applications/io.unom.Punktfunk.Host.desktop"
|
|
# Status tray: per-user SNI icon + XDG autostart entry (self-gating: --autostart exits silently
|
|
# for users who don't run a host) + the hicolor status icons it names.
|
|
install -Dm0755 "$T/punktfunk-tray" "$pkgdir/usr/bin/punktfunk-tray"
|
|
install -Dm0644 "$R/packaging/linux/io.unom.Punktfunk.Tray.desktop" \
|
|
"$pkgdir/etc/xdg/autostart/io.unom.Punktfunk.Tray.desktop"
|
|
local sz png
|
|
for sz in 22x22 48x48; do
|
|
for png in "$R"/packaging/linux/icons/hicolor/$sz/apps/*.png; do
|
|
install -Dm0644 "$png" "$pkgdir/usr/share/icons/hicolor/$sz/apps/$(basename "$png")"
|
|
done
|
|
done
|
|
# headless session helpers + env templates + OpenAPI doc
|
|
install -Dm0755 "$R/scripts/headless/run-headless-kde.sh" "$pkgdir/usr/share/punktfunk/headless/run-headless-kde.sh"
|
|
install -Dm0755 "$R/scripts/headless/run-headless-sway.sh" "$pkgdir/usr/share/punktfunk/headless/run-headless-sway.sh"
|
|
install -Dm0644 "$R/scripts/headless/kde-authorized" "$pkgdir/usr/share/punktfunk/headless/kde-authorized"
|
|
install -Dm0644 "$R/scripts/headless/punktfunk-sink.conf" "$pkgdir/usr/share/punktfunk/headless/punktfunk-sink.conf"
|
|
install -Dm0644 "$R/scripts/host.env.example" "$pkgdir/usr/share/punktfunk/host.env.example"
|
|
install -Dm0644 "$R/packaging/bazzite/host.env" "$pkgdir/usr/share/punktfunk/host.env.bazzite"
|
|
install -Dm0644 "$R/packaging/kde/host.env" "$pkgdir/usr/share/punktfunk/host.env.kde"
|
|
# Headless GAME-mode fix: gamescope-session-plus drop-in that uses the headless backend when no
|
|
# display is connected (so SteamOS/Bazzite "Switch to Game Mode" works on a display-less streaming
|
|
# host). No-op on display-attached boxes; sourced as /etc/gamescope-session-plus/sessions.d/steam.
|
|
install -Dm0644 "$R/packaging/bazzite/gamescope-headless-session" \
|
|
"$pkgdir/etc/gamescope-session-plus/sessions.d/steam"
|
|
install -Dm0644 "$R/api/openapi.json" "$pkgdir/usr/share/punktfunk/openapi.json"
|
|
# firewalld service definitions — NOT auto-enabled (Arch packages never touch the admin's
|
|
# firewall). Stock Arch ships none, so they're a no-op there; CachyOS et al. ship firewalld, so
|
|
# sudo firewall-cmd --reload && sudo firewall-cmd --permanent --add-service=punktfunk-gamestream && sudo firewall-cmd --reload
|
|
# (or =punktfunk-native). See README.md → Firewall.
|
|
install -Dm0644 "$R/packaging/linux/punktfunk-gamestream.xml" \
|
|
"$pkgdir/usr/lib/firewalld/services/punktfunk-gamestream.xml"
|
|
install -Dm0644 "$R/packaging/linux/punktfunk-native.xml" \
|
|
"$pkgdir/usr/lib/firewalld/services/punktfunk-native.xml"
|
|
install -Dm0644 "$R/LICENSE-MIT" "$pkgdir/usr/share/licenses/punktfunk-host/LICENSE-MIT"
|
|
install -Dm0644 "$R/LICENSE-APACHE" "$pkgdir/usr/share/licenses/punktfunk-host/LICENSE-APACHE"
|
|
install -Dm0644 "$R/README.md" "$pkgdir/usr/share/doc/punktfunk-host/README.md"
|
|
}
|
|
|
|
package_punktfunk-client() {
|
|
pkgdesc="Low-latency desktop/game streaming CLIENT — native GTK4/libadwaita Linux app"
|
|
# The GTK4/libadwaita client: SDL3 gamepads, FFmpeg (VAAPI) decode, PipeWire audio/mic.
|
|
depends=('gtk4' 'libadwaita' 'sdl3' 'ffmpeg' 'pipewire' 'wireplumber' 'pipewire-pulse'
|
|
'opus' 'libglvnd')
|
|
optdepends=('libva-mesa-driver: VAAPI hardware decode on AMD (incl. Steam Deck); software fallback otherwise'
|
|
'intel-media-driver: VAAPI hardware decode on Intel'
|
|
'gamescope: run the client fullscreen in a Gaming-Mode session')
|
|
install=punktfunk-client.install
|
|
local R; R="$(_repo)"; local T="$srcdir/target/release"
|
|
|
|
install -Dm0755 "$T/punktfunk-client" "$pkgdir/usr/bin/punktfunk-client"
|
|
install -Dm0644 "$R/packaging/linux/io.unom.Punktfunk.desktop" \
|
|
"$pkgdir/usr/share/applications/io.unom.Punktfunk.desktop"
|
|
# DualSense hidraw access (full pad fidelity through SDL's HIDAPI driver).
|
|
install -Dm0644 "$R/scripts/70-punktfunk-client.rules" \
|
|
"$pkgdir/usr/lib/udev/rules.d/70-punktfunk-client.rules"
|
|
# 32 MB UDP recv buffer (so high-bitrate streams don't overflow the kernel socket buffer).
|
|
install -Dm0644 "$R/scripts/99-punktfunk-client-net.conf" \
|
|
"$pkgdir/usr/lib/sysctl.d/99-punktfunk-client-net.conf"
|
|
install -Dm0644 "$R/LICENSE-MIT" "$pkgdir/usr/share/licenses/punktfunk-client/LICENSE-MIT"
|
|
install -Dm0644 "$R/LICENSE-APACHE" "$pkgdir/usr/share/licenses/punktfunk-client/LICENSE-APACHE"
|
|
}
|
|
|
|
package_punktfunk-web() {
|
|
pkgdesc="punktfunk management web console (Nitro SSR on bun, HTTPS/HTTP-1.1 over TLS) — pairing + status in the browser"
|
|
# bun is the runtime (Bun.serve), and it's a native binary we vendor, so this package is
|
|
# arch-specific (not 'any'). Auto-wired to the host's mgmt token + identity cert via the systemd
|
|
# --user units; enable with `systemctl --user enable --now punktfunk-web`. No nodejs/bun dependency.
|
|
local R; R="$(_repo)"
|
|
|
|
# Pre-built bun-preset bundle (from build()) + a PATH-stable launcher (matches the .deb/.rpm).
|
|
install -d "$pkgdir/usr/share/punktfunk-web/.output"
|
|
cp -r "$R/web/.output/server" "$pkgdir/usr/share/punktfunk-web/.output/server"
|
|
cp -r "$R/web/.output/public" "$pkgdir/usr/share/punktfunk-web/.output/public"
|
|
# Vendor the build env's bun into a private dir so it never collides with a
|
|
# system-wide bun on PATH.
|
|
install -Dm0755 "$(command -v bun)" "$pkgdir/usr/lib/punktfunk-web/bun"
|
|
install -d "$pkgdir/usr/bin"
|
|
printf '%s\n' '#!/bin/sh' 'exec /usr/lib/punktfunk-web/bun /usr/share/punktfunk-web/.output/server/index.mjs "$@"' \
|
|
> "$pkgdir/usr/bin/punktfunk-web-server"
|
|
chmod 0755 "$pkgdir/usr/bin/punktfunk-web-server"
|
|
# systemd USER units: the console runs per-user; web-init generates the login password on first start.
|
|
install -Dm0644 "$R/scripts/punktfunk-web.service" "$pkgdir/usr/lib/systemd/user/punktfunk-web.service"
|
|
install -Dm0644 "$R/scripts/punktfunk-web-init.service" "$pkgdir/usr/lib/systemd/user/punktfunk-web-init.service"
|
|
install -Dm0755 "$R/scripts/web-init.sh" "$pkgdir/usr/share/punktfunk-web/web-init.sh"
|
|
install -Dm0644 "$R/web/web.env.example" "$pkgdir/usr/share/punktfunk-web/web.env.example"
|
|
install -Dm0644 "$R/LICENSE-MIT" "$pkgdir/usr/share/licenses/punktfunk-web/LICENSE-MIT"
|
|
install -Dm0644 "$R/LICENSE-APACHE" "$pkgdir/usr/share/licenses/punktfunk-web/LICENSE-APACHE"
|
|
}
|