gateway: serve the hive dashboard on <hive>.hives.<swarm> behind authelia, drop htpasswd
The dashboard, its API, the swagger UI and the agent routes move to their own vhost, `swarm.dashboardDomain` = `<hive>.hives.<swarm.domain>`, under the swarm domain so authelia's session cookie reaches it. `/`, `/api/` and `/api/docs/` ask authelia through `auth_request`, and authelia's `operatorsOnly` rule for each hive's dashboard name lets only the admins group in. The hive domain keeps matrix discovery and redirects every other path to the new name. The name rides as a SAN on the hive's own gateway leaf: the per-hive bao role allows it, and hive-tls asks for it and checks coverage. HTTP Basic auth is gone: the htpasswd writer and its test, the `hivectl gateway` verbs and host-socket requests, the `gateway.auth` options (now a removed-option error), the unauthorized page and the bcrypt dependency. tmpfiles deletes a leftover gateway.htpasswd, which held bcrypt hashes at 0644. c0re hands out dashboard and agent URLs on the new name (HYPERHIVE_DASHBOARD_DOMAIN), and the swarm controller's hive roster carries each hive's dashboard name for the swarm UI's hive list. Closes #3469
This commit is contained in:
parent
09ad7386b2
commit
92559af8e7
47 changed files with 351 additions and 623 deletions
|
|
@ -135,17 +135,13 @@ Later config changes are PRs on `agent-configs/iris`; you merge them on the
|
|||
forge, and the merge deploys them. →
|
||||
[`agent-lifecycle/config-changes.md`](../agent-lifecycle/config-changes.md#config-changes)
|
||||
|
||||
## Optional · Lock the hive dashboard
|
||||
## The hive dashboard
|
||||
|
||||
The per-hive dashboard has no SSO in front of it. To put it behind HTTP
|
||||
Basic auth, set `services.hyperhive.gateway.auth.enable = true` and add
|
||||
logins:
|
||||
The per-hive dashboard answers on `<hive>.hives.<swarm domain>`, behind
|
||||
authelia: log in with the `admins` account you created above. The hive's
|
||||
own domain redirects there.
|
||||
|
||||
```bash
|
||||
echo "hunter2" | hivectl gateway create-user mara --password-stdin
|
||||
```
|
||||
|
||||
→ [`networking/gateway.md`](../networking/gateway.md#http-basic-auth)
|
||||
→ [`networking/gateway.md`](../networking/gateway.md#dashboard-access)
|
||||
|
||||
## Day to day
|
||||
|
||||
|
|
|
|||
|
|
@ -22,20 +22,22 @@ You rarely switch it on yourself. `gateway.enable` defaults to off, and every mo
|
|||
| `<queue domain>/metrics` | the queue exporter's `/metrics` on loopback, behind an authelia `auth_request`; every other path, `/` included, returns `403`, so `/varz` and `/connz` are never reachable | `swarm-nats.nix`, the queue's host |
|
||||
| `grafana.<swarm>`, `metrics.<swarm>`, `logs.<swarm>`, `otel.<swarm>`, `bao.<swarm>` | the matching swarm service | that service's module → [`swarm/services.md`](../swarm/services.md) |
|
||||
|
||||
**The hive's own vhost**, named for the hive domain. It exists only on a host that runs a hive (`deploy.hive-controller.enable`); a host without a hive has none of these rows:
|
||||
**The hive's own vhosts**: the dashboard's, named `<name>.hives.<swarm>` (`swarm.dashboardDomain`), and one named for the hive domain. They exist only on a host that runs a hive (`deploy.hive-controller.enable`); a host without a hive has none of these rows:
|
||||
|
||||
| URL | upstream | when |
|
||||
| --- | --- | --- |
|
||||
| `<hive>/` | dashboard dist (static, from `servedFrontend`) | always |
|
||||
| `<hive>/api/`, `/health/` | hive-c0re (`7000`) | always |
|
||||
| `<hive>/api/docs/` | themed Swagger UI dist (static) | always |
|
||||
| `<hive>/agent/<name>/` | per-agent harness over its unix socket | `agents.conf` (runtime-generated) |
|
||||
| `<name>.hives.<swarm>/` | dashboard dist (static, from `servedFrontend`), behind authelia | always |
|
||||
| `<name>.hives.<swarm>/api/` | hive-c0re (`7000`), behind authelia | always |
|
||||
| `<name>.hives.<swarm>/health/` | hive-c0re (`7000`) | always |
|
||||
| `<name>.hives.<swarm>/api/docs/` | themed Swagger UI dist (static), behind authelia | always |
|
||||
| `<name>.hives.<swarm>/agent/<name>/` | per-agent harness over its unix socket | `agents.conf` (runtime-generated) |
|
||||
| `<hive>/.well-known/matrix/{client,server}` | inline JSON | `deploy.matrix.enable` |
|
||||
| `<hive>/matrix/` | 301 → `chat.<swarm>/` | `deploy.matrix.enable` and `gatewayHost` set |
|
||||
| `<hive>/` (every other path) | 301 → `<name>.hives.<swarm>`, same path | always |
|
||||
|
||||
The catch-all `_` vhost answers any other `Host` with `444` (connection closed, no response). It's `mkDefault`, so to make your own vhost the default server, set `services.nginx.virtualHosts."_".default = false;` — an eval assertion names both when two claim it.
|
||||
|
||||
Only the host that **runs** authelia declares `auth.<swarm>`; a hive that merely uses SSO knows `swarm.authelia.url` but doesn't answer for that name. The server name must be exactly `swarm.authelia.domain` — authelia checks that `authelia_url` sits inside its session cookie domain at startup, and refuses to boot otherwise. The vhost carries no Basic auth (that would put the login page behind the login it replaces) and passes `X-Forwarded-{Proto,Host,Uri,For}`, because authelia decides by the original request.
|
||||
Only the host that **runs** authelia declares `auth.<swarm>`; a hive that merely uses SSO knows `swarm.authelia.url` but doesn't answer for that name. The server name must be exactly `swarm.authelia.domain` — authelia checks that `authelia_url` sits inside its session cookie domain at startup, and refuses to boot otherwise. The vhost carries no `auth_request` (that would put the login page behind the login it serves) and passes `X-Forwarded-{Proto,Host,Uri,For}`, because authelia decides by the original request.
|
||||
|
||||
⚠️ `auth.<swarm>` answering with the **sso unavailable** page means authelia isn't answering at all — check `journalctl -M swarm-authelia -u authelia-swarm`. While the user set is empty, a disabled placeholder user keeps authelia's user store non-empty, so it boots fine and serves a login page that refuses everyone; add the first account with `swarmctl user add …` ([`setup.md`](../getting-started/setup.md)).
|
||||
|
||||
|
|
@ -109,30 +111,15 @@ nginx reads the directory directly. Keep the key readable by nginx:
|
|||
|
||||
Give the gateway the real cert (`tls.certDir` or `tls.acme`) so it serves proper TLS itself, or front it over a unix socket rather than a plain-http TCP port. `.well-known/matrix/*` responses always advertise `https` ([Discovery flow](#discovery-flow-matrix)).
|
||||
|
||||
## HTTP Basic auth
|
||||
## Dashboard access
|
||||
|
||||
Optional: Basic auth on the hive's dashboard. Add a login first, then enable it — the htpasswd file exists from first boot, and an empty one refuses everyone.
|
||||
The dashboard answers on `<name>.hives.<swarm>` (`swarm.dashboardDomain`, derived from the hive name and `swarm.domain`), behind an authelia `auth_request`. Log in with your authelia account; only accounts in the `admins` group get in, the same rule as the swarm UI. Add one with `swarmctl user add <name> --group admins` ([`swarm/sso.md`](../swarm/sso.md)).
|
||||
|
||||
_On the hive host:_
|
||||
The name sits under the swarm domain so authelia's session cookie reaches it, whatever the hive's own domain is. Any path on the hive domain other than matrix discovery redirects there, so old bookmarks still land.
|
||||
|
||||
```sh
|
||||
hivectl gateway create-user alice --password-stdin # password on stdin
|
||||
hivectl gateway delete-user bob
|
||||
hivectl gateway list-users
|
||||
```
|
||||
**What it gates:** `/`, `/api/` and `/api/docs/`. **Not gated:** `/health/` (for uptime monitors; status only) and the per-agent `/agent/<name>/` routes, which come from `agents.conf` and carry no `auth_request`.
|
||||
|
||||
```nix
|
||||
services.hyperhive.gateway.auth = {
|
||||
enable = true;
|
||||
# realm = "hyperhive"; # default; must not contain `"` or `$`
|
||||
};
|
||||
```
|
||||
|
||||
`hivectl` asks hive-c0re over the host admin socket, and the daemon writes `/var/lib/hive-gateway/conf/gateway.htpasswd` itself, bcrypt (cost 12) with `$2y$` hashes nginx reads natively. `--password <pw>` also works but lands in shell history.
|
||||
|
||||
**What it gates:** `/`, `/api/` and `/api/docs/` on the hive vhost. **Not gated:** `/health/` (for uptime monitors; status only), `/.well-known/matrix/*`, and the per-agent `/agent/<name>/` routes, which come from `agents.conf` and inherit no auth from `/`.
|
||||
|
||||
A failed or missing login gets `401` with a styled `unauthorized.html` naming the `hivectl` command to run, so browsers still show the login dialog first.
|
||||
**Certificate:** in self-signed mode the name is a SAN on the hive's own leaf, issued through its own store role, so it needs nothing extra. With `tls.acme` it needs a public DNS record like any other vhost. With `tls.certDir` your certificate must name it; a `*.<swarm>` wildcard doesn't cover `<name>.hives.<swarm>`.
|
||||
|
||||
## Firewall posture (host-level)
|
||||
|
||||
|
|
@ -211,7 +198,7 @@ When enabled, every vhost adds `Strict-Transport-Security: max-age=…[; include
|
|||
`services.hyperhive.gateway.localHostsEntry = true` maps to `127.0.0.1` in the host's `/etc/hosts`:
|
||||
|
||||
- the hive domain;
|
||||
- every name a module on this host contributes to `gateway.localNames` — each swarm service this host runs adds its own (`forge.<swarm>`, `chat.<swarm>`, `auth.<swarm>`, the swarm UI's apex, …).
|
||||
- every name a module on this host contributes to `gateway.localNames` — the dashboard's `<name>.hives.<swarm>` where a hive runs, and each swarm service this host runs adds its own (`forge.<swarm>`, `chat.<swarm>`, `auth.<swarm>`, the swarm UI's apex, …).
|
||||
|
||||
`services.hyperhive.deploy.singleHostSwarm` turns it on. Leave it off with real DNS.
|
||||
|
||||
|
|
@ -412,7 +399,7 @@ HTML pages instead of nginx's default error chrome:
|
|||
504 = /__hive_agent_unreachable` rewrites to `unreachable.html`.
|
||||
|
||||
`hive-gateway/error-pages.nix` renders every page (`notFound`, `unreachable`,
|
||||
`unauthorized`, `ssoUnavailable`) from one template with `pkgs.writeText`;
|
||||
`ssoUnavailable`) from one template with `pkgs.writeText`;
|
||||
nginx serves each through an `internal` location with `alias` to the file,
|
||||
so only nginx's own error handling can reach them. They depend on nothing
|
||||
from the frontend dist and render even when hive-c0re is down. A service
|
||||
|
|
|
|||
|
|
@ -84,7 +84,9 @@ below. A hive without them reads
|
|||
|
||||
Every row also carries `last_seen_unix` and `age_seconds` if you want to
|
||||
apply your own threshold. The timestamp is the one the queue recorded on
|
||||
arrival, not one the hive put in its own payload.
|
||||
arrival, not one the hive put in its own payload. A roster hive's row
|
||||
carries `dashboard`, the host its dashboard answers on; the swarm UI's
|
||||
hive list links there.
|
||||
|
||||
Set `services.hyperhive.swarm.controller.staleAfterSeconds` (default
|
||||
`120`) **above the rate hives publish at**, or everything reads `stale`
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ debug agent behavior.
|
|||
## For the operator
|
||||
|
||||
- **[hivectl](hivectl.md)** — the curated guide: provisioning forge
|
||||
and matrix accounts, gateway htpasswd management, container
|
||||
and matrix accounts, container
|
||||
lifecycle shortcuts, interactive agent shell access.
|
||||
- **[hivectl-cli](hivectl-cli.md)** — the exhaustive, autogenerated
|
||||
flag-by-flag reference, kept in lockstep with the binary by CI.
|
||||
|
|
|
|||
|
|
@ -9,10 +9,6 @@ This document contains the help content for the `hivectl` command-line program.
|
|||
* [`hivectl forge reconcile-config`↴](#hivectl-forge-reconcile-config)
|
||||
* [`hivectl matrix`↴](#hivectl-matrix)
|
||||
* [`hivectl matrix invite`↴](#hivectl-matrix-invite)
|
||||
* [`hivectl gateway`↴](#hivectl-gateway)
|
||||
* [`hivectl gateway create-user`↴](#hivectl-gateway-create-user)
|
||||
* [`hivectl gateway delete-user`↴](#hivectl-gateway-delete-user)
|
||||
* [`hivectl gateway list-users`↴](#hivectl-gateway-list-users)
|
||||
* [`hivectl agent`↴](#hivectl-agent)
|
||||
* [`hivectl agent restart`↴](#hivectl-agent-restart)
|
||||
* [`hivectl agent pause`↴](#hivectl-agent-pause)
|
||||
|
|
@ -57,7 +53,6 @@ Sibling to the `hive-c0re` daemon binary. Covers host-side admin operations that
|
|||
|
||||
* `forge` — Reconcile an agent's config between this hive and the forge
|
||||
* `matrix` — matrix-tuwunel invites
|
||||
* `gateway` — Gateway htpasswd user management
|
||||
* `agent` — Lifecycle actions on ONE managed agent container. Needs the hive-c0re daemon running
|
||||
* `list-agents` — Show all managed agents with their status and technical state
|
||||
* `quota-enable` — Enable btrfs qgroup accounting on the agent-state filesystem
|
||||
|
|
@ -147,61 +142,6 @@ Invite a matrix user to the hive Space, or a specific room with `--room`. Idempo
|
|||
|
||||
|
||||
|
||||
## `hivectl gateway`
|
||||
|
||||
Gateway htpasswd user management.
|
||||
|
||||
Add, remove, or list users for the gateway's HTTP Basic auth.
|
||||
|
||||
**Usage:** `hivectl gateway <COMMAND>`
|
||||
|
||||
###### **Subcommands:**
|
||||
|
||||
* `create-user` — Add a user or update an existing user's password in the gateway htpasswd
|
||||
* `delete-user` — Remove a user from the gateway htpasswd
|
||||
* `list-users` — List all gateway htpasswd usernames, one per line
|
||||
|
||||
|
||||
|
||||
## `hivectl gateway create-user`
|
||||
|
||||
Add a user or update an existing user's password in the gateway htpasswd.
|
||||
|
||||
Use `--password-stdin` to keep the password out of shell history.
|
||||
|
||||
**Usage:** `hivectl gateway create-user [OPTIONS] <USERNAME>`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<USERNAME>` — Username to add or update
|
||||
|
||||
###### **Options:**
|
||||
|
||||
* `--password <PASSWORD>` — Set the password inline. WARNING: visible in shell history and process listings — prefer `--password-stdin` for sensitive input. Mutually exclusive with `--password-stdin`
|
||||
* `--password-stdin` — Read the password from stdin (single line, trailing newline stripped). Mutually exclusive with `--password`
|
||||
|
||||
|
||||
|
||||
## `hivectl gateway delete-user`
|
||||
|
||||
Remove a user from the gateway htpasswd
|
||||
|
||||
**Usage:** `hivectl gateway delete-user <USERNAME>`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<USERNAME>` — Username to remove
|
||||
|
||||
|
||||
|
||||
## `hivectl gateway list-users`
|
||||
|
||||
List all gateway htpasswd usernames, one per line
|
||||
|
||||
**Usage:** `hivectl gateway list-users`
|
||||
|
||||
|
||||
|
||||
## `hivectl agent`
|
||||
|
||||
Lifecycle actions on ONE managed agent container. Needs the hive-c0re daemon running.
|
||||
|
|
@ -644,7 +584,7 @@ Resolves the URL from the running daemon so custom forge / matrix domains work.
|
|||
|
||||
Possible values:
|
||||
- `home`:
|
||||
The operator dashboard (`https://<domain>/`)
|
||||
The operator dashboard (`https://<hive>.hives.<swarm domain>/`)
|
||||
- `forge`:
|
||||
The forge (Forgejo) web UI
|
||||
- `matrix`:
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ Available via the `hive-c0re` package in the host NixOS config.
|
|||
|
||||
Unlike the `hive-c0re` daemon subcommands (which go through the broker),
|
||||
`hivectl` covers direct host-side administration: manual provisioning of
|
||||
matrix accounts, gateway htpasswd management, container
|
||||
lifecycle shortcuts, and interactive agent shell access.
|
||||
matrix accounts, container lifecycle shortcuts, and interactive agent shell access.
|
||||
|
||||
This page is the curated guide. For the exhaustive flag-by-flag
|
||||
reference autogenerated from the binary's own command tree, see
|
||||
|
|
@ -65,25 +64,6 @@ group; nobody has built that sync yet.
|
|||
invite power (it owns the hive Space, so that case always works).
|
||||
Idempotent — already-member / already-invited is a no-op.
|
||||
|
||||
## Gateway
|
||||
|
||||
Manage users in the gateway's HTTP Basic auth htpasswd file
|
||||
(`services.hyperhive.gateway.auth`). `hivectl` sends the request over the
|
||||
host admin socket; the `hive-c0re` daemon owns the htpasswd file at its
|
||||
canonical path (`/var/lib/hive-gateway/conf/gateway.htpasswd`) and
|
||||
performs the write.
|
||||
|
||||
```bash
|
||||
hivectl gateway create-user alice --password-stdin # add (or update) user; read password from stdin
|
||||
hivectl gateway create-user bob --password hunter2 # add user inline (visible in shell history)
|
||||
hivectl gateway delete-user bob # remove user
|
||||
hivectl gateway list-users # list all usernames, one per line
|
||||
```
|
||||
|
||||
The daemon hashes passwords with BCrypt (cost 12). It creates the file
|
||||
if it doesn't exist. Re-running `create-user` with the same
|
||||
username updates the password hash in place.
|
||||
|
||||
## Agents
|
||||
|
||||
Container lifecycle shortcuts that go through the host admin socket.
|
||||
|
|
@ -229,7 +209,7 @@ Requires the `hive-c0re` daemon to be running.
|
|||
|
||||
```bash
|
||||
hivectl open # operator dashboard (same as `open home`)
|
||||
hivectl open home # operator dashboard (https://<domain>/)
|
||||
hivectl open home # operator dashboard (https://<hive>.hives.<swarm domain>/)
|
||||
hivectl open forge # the forge (Forgejo) web UI
|
||||
hivectl open matrix # the matrix GUI (fluffychat)
|
||||
```
|
||||
|
|
|
|||
Loading…
Reference in a new issue