Watch
0
0
Fork
You've already forked hyperhive
0

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:
atlas 2026-10-15 20:19:23 +02:00 • committed by mara
commit 92559af8e7
47 changed files with 351 additions and 623 deletions

View file

@ -46,14 +46,6 @@ pub fn agent_state_dir(name: &Ident) -> PathBuf {
PathBuf::from(AGENTS_ROOT).join(name.as_str())
}
/// nginx basic-auth credential store for the operator dashboard vhost.
/// `hivectl`'s `--htpasswd-file` clap default.
///
/// Under the gateway's own state dir rather than c0re's, so that nginx
/// can read it without being given access to everything else c0re keeps.
// nix: read by the gateway's nginx on the host (hive-gateway/) — must match.
pub const GATEWAY_HTPASSWD: &str = "/var/lib/hive-gateway/conf/gateway.htpasswd";
/// `/run/hive-agent` — per-agent runtime socket dir root (web UI unix
/// socket + bound marker), one subdir per agent. The gateway's nginx
/// `proxy_pass`es to `agent_web_socket(name)` directly; `hivectl` dials
@ -261,21 +253,6 @@ pub enum HostRequest {
agent: Ident,
direction: ReconcileDirection,
},
/// Add or update a gateway HTTP-Basic user in the daemon's htpasswd file
/// (`paths::GATEWAY_HTPASSWD`). Daemon-side equivalent of `hivectl gateway
/// create-user`: the daemon bcrypt-hashes `password` (cost 12, remapped to
/// the `$2y$` prefix nginx accepts) and writes the entry, so hivectl never
/// touches the file. `password` is read client-side (inline flag or stdin).
/// Returns a confirmation line in [`HostResponse::messages`].
GatewayCreateUser { username: String, password: String },
/// Remove a gateway HTTP-Basic user from the daemon's htpasswd file.
/// Daemon-side equivalent of `hivectl gateway delete-user`. Errors if the
/// user isn't present so a no-op is detectable.
GatewayDeleteUser { username: String },
/// List the gateway HTTP-Basic usernames in the daemon's htpasswd file.
/// Daemon-side equivalent of `hivectl gateway list-users`; the usernames
/// come back in [`HostResponse::messages`], one per line.
GatewayListUsers,
/// Turn on btrfs qgroup accounting on the agent-state filesystem, via
/// the privileged helper. Daemon-side equivalent of `hivectl
/// quota-enable`. Returns advisory lines in [`HostResponse::messages`].
@ -416,7 +393,7 @@ pub struct HiveUrls {
/// Canonical hive domain (`services.hyperhive.domain`).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
/// Operator dashboard root (`https://<domain>/`).
/// Operator dashboard root (`https://<services.hyperhive.swarm.dashboardDomain>/`).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub home: Option<String>,
/// Forge browser URL (`HIVE_FORGE_PUBLIC_URL`) — `None` when