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.
146 lines
4.8 KiB
Bash
146 lines
4.8 KiB
Bash
#!/usr/bin/env bash
|
|
# Post-install verification — confirm each piece is actually wired up.
|
|
# Prints a checklist; non-fatal so the user sees the whole picture.
|
|
|
|
VERIFY_FAILURES=0
|
|
_check() {
|
|
local name="$1"; shift
|
|
if "$@" >/dev/null 2>&1; then
|
|
ok "$name"
|
|
else
|
|
err "$name"
|
|
VERIFY_FAILURES=$((VERIFY_FAILURES + 1))
|
|
fi
|
|
}
|
|
|
|
verify_install() {
|
|
step "Verifying install"
|
|
|
|
_check "sunshine binary on PATH" command -v sunshine
|
|
|
|
local bin
|
|
bin="$(command -v sunshine 2>/dev/null || true)"
|
|
if [[ -n "$bin" ]]; then
|
|
bin="$(readlink -f "$bin")"
|
|
if getcap "$bin" 2>/dev/null | grep -q cap_sys_admin; then
|
|
ok "sunshine has cap_sys_admin (KMS capture ready)"
|
|
else
|
|
err "sunshine missing cap_sys_admin — KMS capture will fail"
|
|
VERIFY_FAILURES=$((VERIFY_FAILURES + 1))
|
|
fi
|
|
fi
|
|
|
|
if id -nG "$USER" | tr ' ' '\n' | grep -qx input; then
|
|
ok "user '$USER' resolves with 'input' group in current shell"
|
|
else
|
|
warn "user '$USER' is NOT in 'input' group in this shell session."
|
|
warn " /etc/group is correct; you need to log out + back in (or 'newgrp input')."
|
|
fi
|
|
|
|
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 present"
|
|
else
|
|
err "uinput udev rule missing"
|
|
VERIFY_FAILURES=$((VERIFY_FAILURES + 1))
|
|
fi
|
|
|
|
if [[ -c /dev/uinput ]]; then
|
|
ok "/dev/uinput exists"
|
|
else
|
|
warn "/dev/uinput not present yet — may appear on next reboot or 'modprobe uinput'"
|
|
fi
|
|
|
|
case "$GPU_VENDOR" in
|
|
nvidia)
|
|
if nvidia-smi --query-gpu=encoder.stats.sessionCount --format=csv,noheader >/dev/null 2>&1; then
|
|
ok "NVENC interface reachable via nvidia-smi"
|
|
else
|
|
warn "Could not query NVENC via nvidia-smi (driver may need a reboot after install)"
|
|
fi
|
|
;;
|
|
amd)
|
|
if command -v vainfo >/dev/null 2>&1 && vainfo 2>/dev/null | grep -qi 'VAEntrypointEncSlice\|VAProfileH264'; then
|
|
ok "VAAPI encoder profiles available"
|
|
else
|
|
warn "VAAPI encoder profiles not confirmed (install libva-utils to verify with 'vainfo')"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
if [[ "${STREAM_MODE:-}" == "headless" ]]; then
|
|
local do_script="$HOME/.local/share/omarchy-moonlight/bin/sunshine-stream-do.sh"
|
|
local undo_script="$HOME/.local/share/omarchy-moonlight/bin/sunshine-stream-undo.sh"
|
|
local conf="$HOME/.config/sunshine/sunshine.conf"
|
|
|
|
if [[ -x "$do_script" ]]; then
|
|
ok "headless do-hook present and executable"
|
|
else
|
|
err "headless do-hook missing or not executable: $do_script"
|
|
VERIFY_FAILURES=$((VERIFY_FAILURES + 1))
|
|
fi
|
|
|
|
if [[ -x "$undo_script" ]]; then
|
|
ok "headless undo-hook present and executable"
|
|
else
|
|
err "headless undo-hook missing or not executable: $undo_script"
|
|
VERIFY_FAILURES=$((VERIFY_FAILURES + 1))
|
|
fi
|
|
|
|
if [[ -f "$conf" ]] && grep -q '^capture = wlr' "$conf"; then
|
|
ok "sunshine.conf has capture = wlr"
|
|
else
|
|
err "sunshine.conf missing 'capture = wlr'"
|
|
VERIFY_FAILURES=$((VERIFY_FAILURES + 1))
|
|
fi
|
|
|
|
if [[ -f "$conf" ]] && grep -q '^global_prep_cmd' "$conf"; then
|
|
ok "sunshine.conf has global_prep_cmd"
|
|
else
|
|
err "sunshine.conf missing 'global_prep_cmd'"
|
|
VERIFY_FAILURES=$((VERIFY_FAILURES + 1))
|
|
fi
|
|
fi
|
|
|
|
local sunshine_cert="$HOME/.config/sunshine/credentials/cacert.pem"
|
|
if [[ -f "$sunshine_cert" ]]; then
|
|
local issuer
|
|
issuer="$(openssl x509 -in "$sunshine_cert" -noout -issuer 2>/dev/null || true)"
|
|
if grep -qF 'omarchy-stream' <<<"$issuer"; then
|
|
ok "Sunshine cert is signed by the omarchy-stream CA"
|
|
if openssl x509 -in "$sunshine_cert" -checkend $((30 * 86400)) -noout >/dev/null 2>&1; then
|
|
ok "Sunshine cert valid for >30 days"
|
|
else
|
|
warn "Sunshine cert expires within 30 days — re-run install.sh to renew"
|
|
fi
|
|
else
|
|
info "Sunshine cert is Sunshine's self-signed default (no CA chain)"
|
|
fi
|
|
else
|
|
info "Sunshine cert not present yet (will be generated on first start)"
|
|
fi
|
|
|
|
if [[ -f /etc/ca-certificates/trust-source/anchors/omarchy-stream-ca.pem ]]; then
|
|
ok "omarchy-stream CA installed in system trust store"
|
|
else
|
|
info "omarchy-stream CA not in system trust store (only matters if --no-certs was used)"
|
|
fi
|
|
|
|
if systemctl --user is-active --quiet sunshine.service; then
|
|
ok "sunshine.service is active"
|
|
if ss -ltn 2>/dev/null | grep -q ':47990 '; then
|
|
ok "web UI listening on :47990"
|
|
else
|
|
warn "web UI port 47990 not yet listening (service may still be starting)"
|
|
fi
|
|
else
|
|
warn "sunshine.service is not active"
|
|
warn " Inspect: journalctl --user -u sunshine -n 50 --no-pager"
|
|
fi
|
|
|
|
if [[ $VERIFY_FAILURES -gt 0 ]]; then
|
|
warn "$VERIFY_FAILURES check(s) failed — see ${BOLD}README.md${RESET}${YELLOW} 'Diagnostics' for fixes."
|
|
else
|
|
ok "All checks passed."
|
|
fi
|
|
}
|