- status.sh: runtime health check (service state, boot wiring, display backend auto-detect, encoder, ports, web UI, /dev/uinput, pairing) ending in a g2g verdict or concrete TODO list
- docs: TROUBLESHOOTING §12 (headless graphical-session.target boot trap) + §13 (X11/NVENC path & stale wlr drop-in env conflict); ARCHITECTURE capture-backend comparison; FOLLOWUPS P3 (installer X11/Ubuntu support); README diagnostics pointer
- lib/{config,packages,permissions,service}.sh, files/sway-headless.service: in-progress Debian/Ubuntu + headless support refinements
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
71 lines
2.8 KiB
Bash
71 lines
2.8 KiB
Bash
#!/usr/bin/env bash
|
|
# Permissions needed for Sunshine on Wayland:
|
|
# - user in 'input' group (so /dev/uinput is usable for virtual gamepad/keyboard/mouse)
|
|
# - udev rule granting 'input' group access to /dev/uinput
|
|
# - cap_sys_admin on the sunshine binary (so KMS capture works without root)
|
|
|
|
UINPUT_RULE_PATH="/etc/udev/rules.d/60-uinput.rules"
|
|
UINPUT_RULE_CONTENT='KERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess", OWNER="root", GROUP="input", MODE="0660"'
|
|
|
|
ensure_input_group() {
|
|
_ensure_user_in_group input
|
|
# On Debian/Ubuntu, /dev/dri/renderD* nodes are mode 0660 owned by
|
|
# root:render, and /dev/dri/card* are root:video. Sway's wlroots renderer
|
|
# needs the render node (Vulkan/GLES FD); KMS capture needs the card node.
|
|
# Arch typically grants both via udev tag=uaccess for the logged-in seat,
|
|
# so we only add explicit memberships on Debian.
|
|
if [[ "${DISTRO:-}" == "debian" ]]; then
|
|
_ensure_user_in_group render
|
|
_ensure_user_in_group video
|
|
fi
|
|
}
|
|
|
|
# Internal: add $USER to a group if it exists and they're not already in it.
|
|
_ensure_user_in_group() {
|
|
local g="$1"
|
|
if ! getent group "$g" >/dev/null 2>&1; then
|
|
info "Group '$g' does not exist on this system — skipping."
|
|
return 0
|
|
fi
|
|
if id -nG "$USER" | tr ' ' '\n' | grep -qx "$g"; then
|
|
ok "User '$USER' already in '$g' group"
|
|
return 0
|
|
fi
|
|
info "Adding '$USER' to '$g' group"
|
|
as_root usermod -aG "$g" "$USER"
|
|
warn "Group '$g' change takes effect on next login (or 'newgrp $g'). For systemd-user"
|
|
warn "services, you must fully log out and back in so the user manager restarts."
|
|
}
|
|
|
|
ensure_uinput_udev_rule() {
|
|
# The sunshine package may ship its own rule under /usr/lib/udev/rules.d/.
|
|
# If a usable rule already exists anywhere udev looks, do nothing.
|
|
if grep -rqs 'KERNEL=="uinput"' /etc/udev/rules.d /usr/lib/udev/rules.d /run/udev/rules.d 2>/dev/null; then
|
|
ok "uinput udev rule already present"
|
|
return 0
|
|
fi
|
|
info "Writing $UINPUT_RULE_PATH"
|
|
echo "$UINPUT_RULE_CONTENT" | as_root tee "$UINPUT_RULE_PATH" >/dev/null
|
|
as_root udevadm control --reload-rules
|
|
as_root udevadm trigger --subsystem-match=misc --action=change || true
|
|
}
|
|
|
|
set_sunshine_capabilities() {
|
|
local bin
|
|
bin="$(command -v sunshine || true)"
|
|
if [[ -z "$bin" ]]; then
|
|
err "sunshine binary not found on PATH after install; cannot set capabilities."
|
|
return 1
|
|
fi
|
|
# Follow symlinks (e.g., /usr/bin/sunshine may itself be a real file; harmless to readlink -f).
|
|
bin="$(readlink -f "$bin")"
|
|
local current
|
|
current="$(getcap "$bin" 2>/dev/null || true)"
|
|
if [[ "$current" == *"cap_sys_admin"* ]]; then
|
|
ok "sunshine binary already has cap_sys_admin set"
|
|
return 0
|
|
fi
|
|
info "Setting cap_sys_admin+p on $bin (required for KMS capture)"
|
|
as_root setcap cap_sys_admin+p "$bin"
|
|
}
|