130 lines
10 KiB
Markdown
130 lines
10 KiB
Markdown
# Swarm UI
|
|
|
|
The swarm's own web surface and the operator's day-to-day view: served by
|
|
the gateway on the **swarm apex** (`services.hyperhive.swarm.domain`),
|
|
readable only by operators. The per-hive dashboard, on each hive's own
|
|
domain, covers host-level detail for one hive.
|
|
|
|
## What it shows
|
|
|
|
The swarm UI is a set of pages. Each one is a card list or a table you open in
|
|
place, and every one reads from [`swarm-controller`](../../../swarm-controller/README.md):
|
|
|
|
| route | what |
|
|
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `/` | the start page: the swarm's name over a digital-rain backdrop with the slug (`hyperhive / we are the wired`, its shaded gradients pulsing in a wave unless reduced motion is on) at the foot, plus a paperclip offering to set up an agent while no `ruth` exists, or her hive declares her destroyed (it opens the create form with `ruth` filled in and the `ruth` archetype picked); the swarm name in the header links here |
|
|
| `/agents` | every agent as a card that opens in place (status, terminal, subagents, and settings with permissions, internet, allowed domains and accounts); create agents (with their permissions, optionally from an [archetype](archetypes.md)), link forge, matrix and GitHub accounts |
|
|
| `/swarm` | what belongs to the whole swarm: a folded **hives** card with the hive directory and each hive's last reported status, a folded **egress** card with the swarm-wide allowed and denied domains, and a folded, **beta** **notification router** card (with a warning banner) holding the router's flows: a switch for each built-in, every flow drawn as a graph, and an editor for custom flows. `/notifications` redirects here |
|
|
| `/agents/<name>/terminal` | one agent's live terminal |
|
|
| `/agents/<name>/subagents/<subagent>/terminal` | one of that agent's subagents' live terminal |
|
|
| `/reports` | three folded cards, each read only once opened: the **alerts** the swarm's Grafana holds now, the firing ones, with a button for the pending, no-data and error ones and a link to Grafana's own alert list; read through the controller with a Viewer service-account token, and a cross-repo **issues** list, and a cross-repo **pull requests** list |
|
|
| `/jobs` | the controller's job graph, where agent creation and credential mints show progress, and under it the swarm builder's recent builds (agent config PRs, and agents built from `internal/meta` before a deploy), with what nix printed when one failed, and the review classifier's recent runs, a try-out on a real PR, and its settings |
|
|
| `/messages` | the swarm-wide message feed: every message between agents, and to them from the operator, reminders and compaction, with a history window and a filter on sender or recipient; a folded **broadcast** card above the feed sends one message to more than one agent at once, and a folded **schedules** card holds the scheduled prompts: add, edit, pause, resume and remove |
|
|
|
|
An agent created here or with `swarmctl agent create` starts `paused`; set it
|
|
`up` from its card. A card shows **login needed** when the agent's claude has no
|
|
session, with a **log in** button that runs the claude login from a dialog (see
|
|
[`claude-login.md`](claude-login.md)). The **wanted** badge changes an agent's
|
|
declared state, destroy included.
|
|
|
|
Each page, its controls and what they send are in
|
|
[the swarm UI reference](../../4-implementation/web-ui/swarm-ui.md).
|
|
|
|
## Enabling
|
|
|
|
```nix
|
|
services.hyperhive.deploy.swarm-controller.enable = true; # the UI comes with it
|
|
```
|
|
|
|
The UI has no switch of its own (setting `deploy.swarm-ui.enable` or
|
|
`swarm.ui.enable` has no effect, and warns at evaluation), and doesn't follow `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.
|
|
|
|
The UI build is `deploy.swarm-controller.ui.package` (defaulted from this
|
|
flake's `swarm-ui` package). The older `deploy.swarm-ui.package` still works
|
|
and warns at evaluation.
|
|
|
|
The UI answers on `services.hyperhive.swarm.domain` and nothing else. It
|
|
shares that name with the swarm-controller it fronts — one service to a
|
|
reader and to a certificate — so there is no separate option to pin.
|
|
|
|
> 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` don't 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`, followed by a `deny` for everyone else. An
|
|
account without that group authenticates fine and still gets bounced.
|
|
|
|
```sh
|
|
swarmctl user add <you> --email <you>@example.com --group admins
|
|
swarmctl user update <you> --add-group admins # an account that already exists
|
|
```
|
|
|
|
`--email` isn't needed for the UI, but the forge won't create your account
|
|
without one → [setup.md § 2](../../1-getting-started/setup.md#2--your-sso-account).
|
|
|
|
Why a group and not "any session": agents are authelia subjects too, so
|
|
_authenticated_ includes every agent in the swarm. The group is the only
|
|
thing standing between "an operator's page" and "anyone with a session."
|
|
|
|
## When your login ends
|
|
|
|
When the session ends while a page is open, the page's next `/api/` request (a
|
|
poll, a form, or a stream that dies) gets a plain 401 with a
|
|
`WWW-Authenticate` header from the gateway, and the page reloads. The reload
|
|
lands on the login and, after you log in, back on the same address. A page
|
|
request still gets the login redirect, and `swarmctl --swarm` still treats the
|
|
401 as a sign to log in again. The page skips a second reload within ten
|
|
seconds, so a page that keeps answering 401 can't loop.
|
|
|
|
## What the browser keeps
|
|
|
|
The vhost tells the browser what to cache. The bundle under `/static/` has
|
|
content hashes in its names, so the browser keeps it for a year. The entry
|
|
document, `/sw.js`, the manifest, the icons and the theme's `colors.css` have
|
|
fixed names, so the browser revalidates them on every load, and a deploy
|
|
reaches an open browser at its next load. A file that doesn't exist answers
|
|
404, including a `/static/` file from an older build, rather than the entry
|
|
document.
|
|
|
|
The service worker fetches its shell past the HTTP cache and refreshes the
|
|
cached entry document on each page load that reaches the network. When its
|
|
install fails, the previous worker keeps running and the browser console shows
|
|
why.
|
|
|
|
The pages carry a content security policy: scripts and connections only from
|
|
this origin, images from this origin, `data:` and https, and no framing from
|
|
another origin.
|
|
|
|
## What it costs to be reachable
|
|
|
|
hyperhive publishes the apex to the hive's resolver like every other
|
|
swarm service, so agent containers can resolve it. That's deliberate and it's
|
|
not a hole: **reachability isn't the access control here.** An agent
|
|
that resolves the name and connects still has no operator session, and
|
|
the subrequest denies it.
|
|
|
|
## Quick links
|
|
|
|
The header has one 🔗 button, on every page, that opens links to the swarm's
|
|
other services: the forge, authelia, Grafana, the metrics and log stores, the
|
|
Matrix client and the secret store's web UI. The list is
|
|
`services.hyperhive.deploy.swarm-controller.links`, which defaults to one entry
|
|
per swarm service. An empty list hides the button. The **Bao** entry admits
|
|
members of authelia's `admins` group only; see
|
|
[`credentials.md`](credentials.md#the-browser-ui). Where each URL comes from, and
|
|
the two places to wire a new swarm service name, are in
|
|
[the reference](../../4-implementation/web-ui/swarm-ui.md#quick-links).
|
|
|
|
## Cross-references
|
|
|
|
- [`sso.md`](sso.md) — the authelia instance itself, and the user store.
|
|
- [`4-implementation/networking/gateway.md`](../../4-implementation/networking/gateway.md) — the full vhost map and TLS modes.
|