Commit Graph

3 Commits

Author SHA1 Message Date
ee1379d5be Add Debian/Ubuntu support via a thin distro dispatch layer
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.
2026-05-23 01:17:42 +00:00
4d2f050e33 Persistent HEADLESS-1 + SSH-tunnel-friendly cert SANs + web UI lockdown
Two streams of fixes shipped together.

Headless persistence (root cause of "Fatal: Unable to find display or
encoder during startup")
- bin/sunshine-stream-undo.sh: stop removing HEADLESS-1 on disconnect.
  Create-on-connect / destroy-on-disconnect raced with Sunshine's startup
  encoder probe and made every restart fail with a fatal-but-misleading
  warning. The output now lives across stream sessions; sunshine-stream-
  do.sh just resizes it per client.
- files/headless-prestart.conf: systemd-user drop-in that runs
  'hyprctl output create headless' (non-fatal) before Sunshine starts, so
  HEADLESS-1 exists before the encoder probe.
- lib/headless.sh: install_headless_prestart_dropin resolves the actual
  unit name (sunshine.service or app-dev.lizardbyte.app.Sunshine.service)
  and lands the drop-in under ~/.config/systemd/user/<unit>.d/.
- lib/service.sh: enable_sunshine_service calls install_headless_prestart_
  dropin when STREAM_MODE=headless. Placed after ensure_sunshine_unit_
  present so the unit name is settled when the drop-in is written.
- install.sh: comment noting the drop-in install is deferred to the
  service-enable step.

Web UI lockdown + tunnel-friendly certs
- lib/config.sh: emits origin_web_ui_allowed = pc. Sunshine rejects web UI
  requests from anywhere other than localhost regardless of bind address.
  Streaming/pairing (47989) stays LAN-accessible. Inline comment documents
  the SSH tunnel recipe.
- lib/certs.sh: add DNS:localhost and IP:127.0.0.1 to host cert SANs so
  the tunneled https://localhost:47990 URL doesn't trigger a hostname
  mismatch. Idempotency check now requires those SANs too.

Misc.
- files/sunshine.service: fallback unit also gains the prestart ExecStartPre.
- lib/service.sh: ensure_sunshine_unit_present aliases the reverse-DNS
  Sunshine unit as sunshine.service when sunshine-bin's short-name unit
  isn't installed.
2026-05-18 11:53:18 -06:00
e878b392e4 Sign Sunshine certs with a 1Password-backed root CA
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.
2026-05-18 10:43:33 -06:00