Adds a parallel install path for Debian/Ubuntu hosts alongside the existing
Arch/Omarchy/Hyprland one. The Arch path is untouched at runtime; everything
new is gated on $DISTRO and (for headless) $COMPOSITOR.
Highlights:
- lib/distro.sh: detect_distro + pkg_install/pkg_remove/ca_anchor_path/
ca_update_trust dispatch helpers
- lib/packages.sh: Ubuntu sunshine install pulls LizardByte's official .deb
from GitHub releases (override via SUNSHINE_DEB_URL/SUNSHINE_DEB_VERSION);
GPU encoder packages branch per $DISTRO:$GPU_VENDOR
- bin/sunshine-stream-{do,undo,prestart}-sway.sh + files/sway-headless.*:
swaymsg-based headless capture path for hosts without Hyprland. sway runs
under a systemd-user unit that sunshine.service depends on via drop-in.
- lib/preflight.sh: clearer NVIDIA driver guidance on Ubuntu (we don't install
the driver - too many branch/kernel/Secure-Boot variants); sway-aware
headless preflight
- lib/certs.sh + lib/verify.sh + uninstall.sh: distro-aware CA trust anchor
(Arch: /etc/ca-certificates/trust-source/anchors + update-ca-trust;
Debian: /usr/local/share/ca-certificates + update-ca-certificates)
Verified on Ubuntu 24.04: ./install.sh --doctor --headless loads cleanly,
distro/GPU/compositor detection report the right values, all pre-install
failures correspond to the actual missing pieces.
When sunshine-bin trips the ldd check and we switch to the source build,
the prior install left sunshine-bin-debug behind. The source package
includes its own sunshine-debug which collides on
/usr/lib/debug/usr/bin/sunshine.debug, so pacman refuses the install.
Remove both sunshine-bin and sunshine-bin-debug before yay -S sunshine.
uninstall.sh similarly drops all four variants.
Replaces Sunshine's self-signed cert with one minted from a private root CA
whose key material lives in 1Password. Every host running install.sh fetches
the CA via 'op read', mints itself a host cert with SANs for <hostname>.lan
and the current LAN IP, and installs the CA into the system trust store.
Bootstrap (run once, anywhere)
- scripts/cert-bootstrap.sh: generates a 4096-bit RSA root CA (10y validity),
uploads it as a Secure Note titled "Omarchy-Stream Root CA" in the Private
vault with two fields: cert (text) and key (concealed). Refuses to overwrite
an existing item without --force.
Per-host (lib/certs.sh)
- fetch_and_install_certs: reads op://Private/Omarchy-Stream Root CA/{cert,key}
to a tmpfs-staged temp dir (XDG_RUNTIME_DIR), mints a host cert via openssl
with serverAuth + clientAuth EKU, drops cert/key at ~/.config/sunshine/
credentials/{cacert,cakey}.pem, installs the CA at
/etc/ca-certificates/trust-source/anchors/omarchy-stream-ca.pem and runs
update-ca-trust.
- Idempotent: skips re-mint when on-disk cert is signed by the current CA,
has the expected SANs, and isn't within 30 days of expiry. Override with
FORCE_CERTS=1 or --force-certs.
install.sh
- Adds --no-certs, --force-certs flags; sources lib/certs.sh; runs cert step
after permissions/config and before firewall so the service restart at the
end of install picks up the new cert.
client/install-macos.sh
- After installing Moonlight, if `op` is available and signed in, fetches the
CA and adds it as a trusted root to /Library/Keychains/System.keychain via
`security add-trusted-cert -d -r trustRoot`. Skips cleanly when op isn't
ready.
uninstall.sh
- Adds --remove-ca-trust to delete the system trust anchor. By default the
CA is left in place since other tools may rely on it.
verify.sh
- Adds checks for: cert signed by omarchy-stream CA, cert >30 days from
expiry, CA present in system trust store.
Docs
- README "Trusted TLS certs via 1Password" section: bootstrap flow, per-host
flow, client trust matrix (Linux / macOS / iOS / Android / Apple TV),
re-pairing note (first cert install on a host invalidates pinned Moonlight
fingerprints), config env vars.
- client/README gains per-platform CA-trust install steps with concrete
`op read` + platform-specific commands.
Layers a few things on top of the initial scaffold:
- Default to sunshine-bin (precompiled, ~seconds) instead of building from
source. --from-source restores the old behavior.
- Add lib/preflight.sh: catches the gotchas before any work is done —
Wayland session, NVIDIA driver responsive, nvidia-drm.modeset, amdgpu
loaded, pipewire-pulse present, SSH-without-session warning.
- Add lib/config.sh: writes a tuned ~/.config/sunshine/sunshine.conf with
per-vendor encoder settings (NVENC P1+ll+cbr, VAAPI ultralowlatency,
QuickSync veryfast), KMS capture, pulse audio sink. Uses a
"# managed-by: omarchy-moonlight" marker; removing it hands ownership
back to the user and the installer won't touch the file again.
- Add lib/verify.sh: post-install verification of every step
(cap_sys_admin set, group resolves, udev rule present, /dev/uinput
exists, encoder reachable, service active, :47990 listening). Same
checks are reachable standalone via --doctor.
- Install runtime helpers (pipewire-pulse, vulkan-tools, libva-utils)
alongside Sunshine for diagnostics + audio.
- Uninstall handles both sunshine + sunshine-bin and the -bin moonlight
variant.
- README documents the tuning table, the new flags, and the modeset
troubleshooting path.
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