Root cause: gnome-remote-desktop-setup.service ran as root but dropped
privileges via `runuser -u gnome-remote-desktop`. Non-root grdctl --system
attempts authorisation through pkexec. The Nix-store pkexec binary is not
setuid, so every system-mode credential call silently failed while the script
still printed "configured successfully". GNOME Remote Desktop then started
without applied credentials, causing Remmina to loop at the login dialog.
Fix:
- Remove `runuser -u gnome-remote-desktop --` from grdctl_system helper;
the root-run oneshot service can call grdctl --system directly.
- Remove pkgs.polkit and pkgs.util-linux from the setup service path as
neither polkit nor runuser is needed any more.
- Update tests: rename test_setup_runs_grdctl_as_gnome_remote_desktop_user
to test_setup_runs_grdctl_directly_as_root and assert that runuser,
pkexec, and sudo are absent; add
test_privilege_escalation_packages_absent_from_setup_path.
All 21 app/tests pass.
1. Add nix-bitcoin.generateSecrets = lib.mkDefault true global compat
default in role-logic.nix so Desktop Only systems can evaluate while
nix-bitcoin is still globally imported by the flake.
2. Harden Desktop Only role: change all server/node service and feature
disables from lib.mkDefault false to lib.mkForce false so they cannot
be overridden by custom.nix or option defaults.
- sovran_systemsOS.services: synapse, bitcoin, vaultwarden, wordpress, nextcloud
- sovran_systemsOS.features: haven, mempool, element-calling, bitcoin-core
- sovran_systemsOS.web.btcpayserver
3. Make Caddy conditional in caddy.nix:
enable = needsHttpsPorts || extraVhosts != ""
so Caddy does not run on Desktop Only installs with no web services.
LiveKit was exiting cleanly with "TURN domain required" because turn.enabled
was set in the build-time config but turn.domain was never provided to the
process (the old livekit-runtime-config.service wrote a YAML that nothing
read). A clean exit (status 0) meant Restart=on-failure never restarted it,
so the Hub reported the service as Inactive.
This replaces the dead runtime-config oneshot with livekit-turn-setup.service,
which at runtime:
- reads the matrix domain from /var/lib/domains/matrix (no hardcoding)
- copies Caddy's already-issued matrix cert/key into /var/lib/livekit
- generates a complete LiveKit config (incl. turn.domain + TLS cert/key)
at /run/livekit/livekit.yaml
The livekit.service ExecStart is overridden to load that runtime config
(mirroring the existing Caddy ExecStart override pattern in
modules/core/caddy.nix), since turn.domain is only known at runtime. The cert
is delivered via LoadCredential so it is readable under DynamicUser=true
without weakening the sandbox.
Also aligns the RTC media port range (rtc.port_range_start/end = 30000-40000)
so it matches the forwarded ports, and drops the now-redundant manual
30000-40000 firewall ranges (covered by services.livekit settings/openFirewall).