Initial scaffold: idempotent Sunshine + Moonlight installer for Omarchy

Sets up bidirectional game streaming across Omarchy/Hyprland/Wayland
machines (NVIDIA desktop and AMD Framework laptop), with the Macbook
as an additional Moonlight client.

The same install.sh runs on either machine; GPU vendor is detected at
runtime and the appropriate hardware-encode packages are installed.

Includes:
- KMS capture setup (cap_sys_admin on sunshine, input group, uinput udev rule)
- ufw / firewalld port opening when a firewall is active
- systemd --user service + loginctl enable-linger for always-on hosting
- uninstall.sh with --purge for user data removal
- Flags to install host-only or client-only
This commit is contained in:
2026-05-18 10:11:53 -06:00
commit a9dcbc1db8
11 changed files with 572 additions and 0 deletions

54
lib/firewall.sh Normal file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env bash
# Open Sunshine's ports on whatever firewall is active.
# Sunshine ports:
# TCP: 47984, 47989, 47990, 48010
# UDP: 47998, 47999, 48000, 48010
SUNSHINE_TCP_PORTS=(47984 47989 47990 48010)
SUNSHINE_UDP_PORTS=(47998 47999 48000 48010)
_firewalld_active() { systemctl is-active --quiet firewalld 2>/dev/null; }
_ufw_active() { command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -q "Status: active"; }
_iptables_has_rules() {
command -v iptables >/dev/null 2>&1 || return 1
# Heuristic: more than the default 3 chains-with-no-rules output lines means rules exist.
[[ "$(as_root iptables -S 2>/dev/null | wc -l)" -gt 3 ]]
}
open_sunshine_ports() {
if _firewalld_active; then
info "firewalld is active — opening ports"
local p
for p in "${SUNSHINE_TCP_PORTS[@]}"; do
as_root firewall-cmd --permanent --add-port="${p}/tcp" >/dev/null
done
for p in "${SUNSHINE_UDP_PORTS[@]}"; do
as_root firewall-cmd --permanent --add-port="${p}/udp" >/dev/null
done
as_root firewall-cmd --reload >/dev/null
ok "Opened Sunshine ports in firewalld"
return 0
fi
if _ufw_active; then
info "ufw is active — opening ports"
local p
for p in "${SUNSHINE_TCP_PORTS[@]}"; do
as_root ufw allow "${p}/tcp" >/dev/null
done
for p in "${SUNSHINE_UDP_PORTS[@]}"; do
as_root ufw allow "${p}/udp" >/dev/null
done
ok "Opened Sunshine ports in ufw"
return 0
fi
if _iptables_has_rules; then
warn "iptables rules detected but no managed firewall (ufw/firewalld). Open these ports manually:"
warn " TCP: ${SUNSHINE_TCP_PORTS[*]}"
warn " UDP: ${SUNSHINE_UDP_PORTS[*]}"
return 0
fi
info "No active firewall detected — nothing to configure."
}