docs(3167): the swarm UI page, and the group step that gates it
New docs/swarm/ui.md (split-page shape, per the docs rule), linked from the swarm README and added to the gateway's vhost map. Leads with the step that separates 'protected' from 'locked out': swarmctl user add <you> --group operators. auth_request asks whether there is a session; the access_control rule is what makes it mean operator, and an account created before the rule existed has no groups. Also records the four wiring sites a swarm service name needs, with the certificate one called out - serviceDomains is both the sub-CA's nameConstraints set and the leaf's SANs, and the apex is a sibling of the other three rather than a parent, so nothing issues for it implicitly.
This commit is contained in:
parent
600fa15afe
commit
470d2ad845
3 changed files with 87 additions and 0 deletions
|
|
@ -15,6 +15,7 @@ Single nginx in front of every hyperhive web surface. Runs on the **host**, next
|
|||
| `matrix.<hive>/` | `matrix.<hive>` | fluffychat-web static | `matrix.gui.enable` |
|
||||
| `matrix.<hive>/config.json` | `matrix.<hive>` | inline JSON (FluffyChat boot config) | `matrix.gui.enable && domain != null` |
|
||||
| `auth.<swarm>/` | `auth.<swarm>` | authelia (`9091`) | `swarm.authelia.enable` |
|
||||
| `<swarm>/` | `<swarm>` | swarm-ui dist (static), behind an authelia subrequest | `swarm.ui.enable` |
|
||||
|
||||
The authelia vhost is declared only by the host that **runs** authelia, not by every hive that uses it — a client hive knows the swarm's `authelia.url` but must not answer for a name it doesn't serve. Its server name is exactly `swarm.authelia.domain`: authelia validates `authelia_url ⊂ session cookie domain` at startup, so a near-miss is a container that refuses to boot. It carries no `auth_basic` — the login page must not sit behind the login mechanism it replaces — and sets the four `X-Forwarded-{Proto,Host,Uri,For}` headers, since authelia decides by the *original* request rather than the hop it sees.
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,12 @@ Which secrets the SSO provider generates, which one has a reader in
|
|||
another container, and the three ways that one gets delivered:
|
||||
[`sso.md`](sso.md).
|
||||
|
||||
## Swarm UI
|
||||
|
||||
The operator-only web surface on the swarm apex, why reaching it needs
|
||||
the `operators` group rather than just a session, and the four sites a
|
||||
swarm service name has to be wired into: [`ui.md`](ui.md).
|
||||
|
||||
## The swarm's hive directory
|
||||
|
||||
```nix
|
||||
|
|
|
|||
80
docs/swarm/ui.md
Normal file
80
docs/swarm/ui.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# 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
|
||||
|
||||
```nix
|
||||
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 one `server_name` do not error — nginx picks one — so this is
|
||||
> an assertion rather than a runtime surprise.
|
||||
|
||||
## 🔑 You must be in the `operators` 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:operators`. An account without that group authenticates
|
||||
fine and still gets bounced.
|
||||
|
||||
```sh
|
||||
swarmctl user add <you> --group operators
|
||||
```
|
||||
|
||||
An account created before this existed has no groups. Re-add it with the
|
||||
flag — `swarmctl` treats an 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`](sso.md) — the authelia instance itself, and the user store.
|
||||
- [`../gateway.md`](../gateway.md) — the full vhost map and TLS modes.
|
||||
Loading…
Reference in a new issue