#!/usr/bin/env bash # punktfunk — Steam Deck HOST update: rebuild from the current source + restart the services. # Run on the Deck after pulling/rsyncing new source. Pairings, config, and the web login persist. # # bash scripts/steamdeck/update.sh # rebuild host (+web if installed) and restart # bash scripts/steamdeck/update.sh --pull # `git pull` first (if the source is a git checkout) # set -euo pipefail log() { printf '\033[1;36m==>\033[0m %s\n' "$*"; } ok() { printf '\033[1;32m ok\033[0m %s\n' "$*"; } # warn was USED below but never defined — under `set -e` the first warn call ("command not # found") aborted the whole update before the service restarts. warn() { printf '\033[1;33m !!\033[0m %s\n' "$*" >&2; } die() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; } SRC="${PUNKTFUNK_SRC:-$HOME/punktfunk}" BOX="${PUNKTFUNK_BOX:-pf2}" TARGET_DIR="$SRC/target-steamos" [ -d "$SRC/crates/punktfunk-host" ] || die "no punktfunk source at $SRC (set PUNKTFUNK_SRC)" WEB=0; [ -f "$HOME/.config/systemd/user/punktfunk-web.service" ] && WEB=1 if [ "${1:-}" = "--pull" ]; then if [ -d "$SRC/.git" ]; then log "git pull"; git -C "$SRC" pull --ff-only; ok "pulled"; else die "$SRC is not a git checkout — rsync new source then run without --pull"; fi fi log "Rebuilding host (release)" # vulkan-encode matches the packaged builds (deb/arch) — see install.sh. distrobox enter "$BOX" -- bash -lc "set -e; export PATH=\$HOME/.cargo/bin:\$PATH CARGO_TARGET_DIR='$TARGET_DIR'; cd '$SRC' && cargo build -r -p punktfunk-host --features punktfunk-host/vulkan-encode" ok "host rebuilt" if [ "$WEB" = 1 ]; then log "Rebuilding web console" distrobox enter "$BOX" -- bash -lc "set -e; export PATH=\$HOME/.bun/bin:\$PATH; cd '$SRC/web' && bun install --frozen-lockfile && bun run build" ok "web rebuilt" fi # Plugin runner (scripting): rebuild the user-scoped runner payload (install.sh §2b) — also # RETROFITS it onto older installs that predate it (the "plugin runner isn't installed" console # state on SteamOS). log "Rebuilding plugin runner (scripting)" mkdir -p "$HOME/.local/bin" "$HOME/.local/lib/punktfunk-scripting" "$HOME/.local/share/punktfunk-scripting" distrobox enter "$BOX" -- bash -lc "set -e; export PATH=\$HOME/.bun/bin:\$PATH; cd '$SRC/sdk' && bun install --frozen-lockfile --ignore-scripts && bun build src/runner-cli.ts --target=bun --outfile \"\$HOME/.local/share/punktfunk-scripting/runner-cli.js\" && install -m0755 \"\$(command -v bun)\" \"\$HOME/.local/lib/punktfunk-scripting/bun\"" grep -q 'attempt=' "$HOME/.local/share/punktfunk-scripting/runner-cli.js" \ || die "runner bundle missing the dynamic plugin import — wrong build" cat > "$HOME/.local/bin/punktfunk-scripting" <<'WRAP' #!/bin/sh # Generated by scripts/steamdeck/update.sh — user-scoped punktfunk-scripting (see install.sh §2b). exec "$HOME/.local/lib/punktfunk-scripting/bun" "$HOME/.local/share/punktfunk-scripting/runner-cli.js" "$@" WRAP chmod 0755 "$HOME/.local/bin/punktfunk-scripting" sed 's|^ExecStart=.*|ExecStart=%h/.local/bin/punktfunk-scripting|' \ "$SRC/scripts/punktfunk-scripting.service" > "$HOME/.config/systemd/user/punktfunk-scripting.service" systemctl --user daemon-reload ok "plugin runner rebuilt (opt-in service: systemctl --user enable --now punktfunk-scripting)" # Retrofit config that install.sh now writes but older installs predate (both idempotent): # RADV_PERFTEST — Van Gogh RADV still gates VK_KHR_video_encode_* behind it; without it the # Vulkan backend can't open and sessions silently fall back to libav VAAPI. The KWin .desktop — # KWin only grants the restricted capture/input globals to the exe a .desktop authorizes. HOST_ENV="$HOME/.config/punktfunk/host.env" if [ -f "$HOST_ENV" ] && ! grep -q '^RADV_PERFTEST=' "$HOST_ENV"; then printf '\n# Van Gogh RADV gates VK_KHR_video_encode_* behind this (Vulkan Video encode).\nRADV_PERFTEST=video_encode\n' >> "$HOST_ENV" ok "host.env: added RADV_PERFTEST=video_encode" fi mkdir -p "$HOME/.local/share/applications" sed "s|^Exec=.*|Exec=$TARGET_DIR/release/punktfunk-host|" "$SRC/packaging/linux/io.unom.Punktfunk.Host.desktop" \ > "$HOME/.local/share/applications/io.unom.Punktfunk.Host.desktop" ok "KWin desktop-capture authorization refreshed" # Retrofit the system bits install.sh now sets up but older installs predate (idempotent). vhci-hcd = # usbip transport for the native Steam Deck pad; 60-punktfunk.rules = /dev/uhid + vhci access; input # group = uhid write; the kde-authorized grant (per-user, no root) = Desktop-mode input. A stock Deck # needs a sudo PASSWORD, so PROMPT for it rather than silently skipping (skipping = gamepads stay dead). SUDO_OK=0 if sudo -n true 2>/dev/null; then SUDO_OK=1 elif [ -t 0 ]; then warn "sudo needs your password to (re)apply the gamepad udev rule, vhci-hcd, input group, and UDP buffers:" sudo -v && SUDO_OK=1 || true fi if [ "$SUDO_OK" = 1 ]; then if [ -f "$SRC/scripts/60-punktfunk.rules" ]; then sudo install -m644 "$SRC/scripts/60-punktfunk.rules" /etc/udev/rules.d/60-punktfunk.rules sudo udevadm control --reload-rules >/dev/null 2>&1 || true sudo udevadm trigger >/dev/null 2>&1 || true ok "gamepad udev rule ensured" fi if [ -f "$SRC/scripts/punktfunk-modules.conf" ]; then sudo install -m644 "$SRC/scripts/punktfunk-modules.conf" /etc/modules-load.d/punktfunk.conf sudo modprobe vhci-hcd 2>/dev/null || true ok "vhci-hcd autoload ensured (native Steam Deck controller)" fi # UDP buffers: older installs (or sudo-skipped ones) still run the stock 416 KB cap. if [ ! -f /etc/sysctl.d/99-punktfunk-net.conf ]; then printf 'net.core.wmem_max=33554432\nnet.core.rmem_max=33554432\n' | sudo tee /etc/sysctl.d/99-punktfunk-net.conf >/dev/null sudo sysctl -q -p /etc/sysctl.d/99-punktfunk-net.conf >/dev/null 2>&1 || true ok "UDP socket buffers raised to 32 MB (persisted)" fi if id -nG "$USER" | grep -qw input; then :; else sudo usermod -aG input "$USER" warn "added $USER to the 'input' group — REBOOT (or log out/in) for it to apply" fi # Register the tuning on Valve's atomic-update preserve list (see install.sh §4): without # this, every SteamOS A/B update strips the three files above again (verified live — # gamepads silently degrade to Xbox 360, UDP buffers back to 208 KB). if [ -f "$SRC/scripts/punktfunk-atomic-keep.conf" ]; then sudo install -Dm644 "$SRC/scripts/punktfunk-atomic-keep.conf" /etc/atomic-update.conf.d/punktfunk.conf ok "system tuning registered to survive SteamOS updates (atomic-update.conf.d)" fi else warn "no usable sudo — SKIPPED gamepad/udev/vhci/UDP tuning (all root-only; no user-space alternative)." warn "A stock SteamOS 'deck' account has NO password — set one with 'passwd', then re-run. Gamepads stay" warn "Xbox-360 until this runs and you reboot." fi echo warn "If the controller still shows as an Xbox 360 pad, REBOOT the Deck once — the 'input' group and the" warn "vhci-hcd module only become live for the host service on a fresh login." GRANT_SRC="$SRC/scripts/headless/kde-authorized" GRANT_DST="$HOME/.local/share/flatpak/db/kde-authorized" if [ ! -s "$GRANT_DST" ] && [ -s "$GRANT_SRC" ]; then mkdir -p "$(dirname "$GRANT_DST")" install -m644 "$GRANT_SRC" "$GRANT_DST" ok "seeded KDE RemoteDesktop grant (Desktop-mode input)" fi log "Restarting services" systemctl --user restart punktfunk-host.service ok "punktfunk-host restarted" if [ "$WEB" = 1 ]; then systemctl --user restart punktfunk-web.service; ok "punktfunk-web restarted"; fi echo log "Updated. Status: systemctl --user status punktfunk-host"