Both halves of the old name were wrong about the subject. The services
are required of the SWARM, not of the host, and the option says whether
THIS host runs them — so it described the wrong thing and sat in the
namespace that has to be identical on every host. The new name is mara's
own phrasing of what it means: "deploy all swarm level services on this
host".
mkRenamedOptionModule carries existing configs, read-side references
included, so this warns rather than failing to evaluate.
Three sites were not just the identifier:
- local-defaults.nix set it inside `config.services.hyperhive.swarm =
{ … }`. It moves out as a path beside the other deploy.* setter rather
than into a second `deploy = { … }` attrset — the warning that file
already carries about `swarm` applies to any second definition of the
same parent.
- swarm-required-services.nix bound only `swarmCfg`, now unused; it binds
and reads `deployCfg`.
- Two comments in that file described a half-migrated state, where the
switch asserted some `swarm.*.enable` toggles and some `deploy.*` ones.
Every one of them has been `deploy.*` for several slices now.
113 lines
5 KiB
Markdown
113 lines
5 KiB
Markdown
# 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.deploy.swarm-ui.enable = true; # defaults to deploy.swarm-controller.enable
|
|
```
|
|
|
|
Derived from the controller rather than from `allSwarmServices`:
|
|
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 `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.
|
|
|
|
```sh
|
|
swarmctl user add <you> --group admins
|
|
```
|
|
|
|
`admins` deliberately, not a new word: [`../setup.md`](../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` reads the existing entry out of `users.yml`, 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.
|
|
|
|
## Two wiring sites
|
|
|
|
Adding a swarm service name means touching two things. Missing the
|
|
second ships as a different flavour of "works from the host, broken from
|
|
a container":
|
|
|
|
| site | file |
|
|
| --- | --- |
|
|
| vhost + `gateway.localNames` | the service's own module (e.g. `nix/host-modules/swarm-ui.nix`) |
|
|
| **certificate name** | `nix/host-modules/swarm.nix` (`serviceDomains`) |
|
|
|
|
The DNS record and the local-dev `/etc/hosts` entry need no separate
|
|
edit: both are derived from `services.hyperhive.gateway.localNames`,
|
|
which a service's own module already has to push its domain into to be
|
|
resolvable — see `nix/host-modules/hive-gateway/dnsmasq.nix` and
|
|
`.../default.nix`'s `networking.hosts`. `vhosts.nix` itself is scoped to
|
|
the surface the hive's own domain serves (dashboard, per-agent routing,
|
|
matrix discovery); a swarm service declares its own vhost next to its
|
|
own options, the way `swarm-ui.nix` and `swarm-authelia.nix` do.
|
|
|
|
⚠️ 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.
|
|
|
|
## Quick links
|
|
|
|
The swarm UI's header carries a single 🔗 button, visible on every route,
|
|
opening a popover of links to other swarm-wide services — authelia,
|
|
matrix, forge, this UI's own swagger docs. Backed by `GET /api/links`
|
|
(swarm-controller), which serves `services.hyperhive.swarm.controller.links`
|
|
(a `listOf { label, icon, url }`, same shape as the per-agent
|
|
`hyperhive.dashboardLinks`).
|
|
|
|
Rather than one central hardcoded list, each service's own module
|
|
contributes its own entry when it's actually enabled on the controller's
|
|
host — `swarm-authelia.nix`, `hive-matrix.nix` and `hive-forge/default.nix`
|
|
all do, the same list-merge idiom `gateway.localNames` uses above. Adding a
|
|
link for a new service is a nix-only change to that service's own module
|
|
(or an operator adding an entry directly); no swarm-controller or swarm-ui
|
|
change needed. Empty list hides the button rather than showing an empty
|
|
popover.
|
|
|
|
## 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.
|