Per mara on the PR: the guide someone follows on a fresh deploy is a different page from the one they read while debugging, and only the second existed. Also fixes a contradiction the request surfaced: setup.md and swarm/sso.md have told every operator to create '--group admins' since the bootstrap step existed, while the new rule required 'operators'. This is the first rule that CONSUMES a group name, so it takes the one the guide already creates - inventing a second would have meant every account made by following the guide silently failing the check it was supposed to pass, and for mara specifically a migration step that now may not be needed at all. setup.md's step 3 says why --group is not decoration; the new step 4 says what decides whether the page opens (the group, and the name resolving) rather than listing a command, because there is nothing to run. Steps renumbered, including the matrix block's internal 4a-4e.
3.6 KiB
Swarm UI
The swarm's own web surface, served by the gateway on the swarm apex
(services.hyperhive.swarm.domain) and readable only by operators.
Distinct from the per-hive dashboard, which lives on the hive domain and answers for one host. This one is the view across hives.
Enabling
services.hyperhive.swarm.ui.enable = true; # defaults to swarm.controller.enable
Derived from the controller rather than from enableRequiredServices:
the UI is a view onto the controller's state and reaches it over that
daemon's socket, so the host that runs the controller is the host that
can serve the UI. A hive that merely uses a swarm has nothing to serve.
swarm.ui.domain defaults to the swarm apex and can be pinned, the same
way swarm.forge.domain and swarm.matrix.gatewayHost can.
The apex must differ from
services.hyperhive.domain. The gateway's default server already answers for the hive domain, and two vhosts claiming oneserver_namedo not error — nginx picks one — so this is an assertion rather than a runtime surprise.
🔑 You must be in the admins group
This is the step that separates "protected" from "locked out". The
vhost's auth_request asks authelia "is there a session"; the rule
that makes it mean "is this an operator" is an access_control entry
requiring group:admins. An account without that group authenticates
fine and still gets bounced.
swarmctl user add <you> --group admins
admins deliberately, not a new word: ../setup.md has
told every operator to create exactly that group since the bootstrap step
existed, so an account made by following the guide already passes. This
is the first rule that consumes a group name — inventing a second one
would have meant those accounts silently failing a check they were
supposed to pass.
An account created without any group needs re-adding with the flag —
swarmctl treats the existing entry as the canonical store, so the group
is what changes.
Why a group and not a list of usernames: agents are getting authelia accounts of their own (matrix SSO), and authenticated would then include every agent in the hive. The group is the only thing standing between "an operator's page" and "anyone with a session".
What it costs to be reachable
The apex is published to the hive's resolver like every other swarm service, so agent containers can resolve it. That is deliberate and it is not a hole: reachability is not the access control here. An agent that resolves the name and connects still has no operator session, and the subrequest denies it.
Four wiring sites
Adding a swarm service name means touching all four. Missing one ships as a different flavour of "works from the host, broken from a container":
| site | file |
|---|---|
| vhost | nix/host-modules/hive-gateway/vhosts.nix |
| certificate name | nix/host-modules/swarm.nix (serviceDomains) |
| DNS record | nix/host-modules/hive-gateway/dnsmasq.nix |
| local-dev hosts | nix/host-modules/hive-gateway/default.nix |
⚠️ The certificate one is the least obvious and the most visible when
missed. serviceDomains is both the services sub-CA's
nameConstraints set and the leaf's SAN list, and the apex is a
sibling of forge.<swarm> / chat.<swarm> / auth.<swarm>, not a
parent — no CA in the hierarchy issues for it implicitly. Left out, the
vhost falls back to the hive leaf and the swarm's front page opens with a
name mismatch.
Cross-references
sso.md— the authelia instance itself, and the user store.../gateway.md— the full vhost map and TLS modes.