reshape swarm peers: domain-as-key, certFingerprint field
This commit is contained in:
parent
a8e8c50a30
commit
52cfc3ea1c
3 changed files with 45 additions and 66 deletions
|
|
@ -51,14 +51,14 @@ pub fn swarm_name() -> Option<String> {
|
|||
/// One peer hive in the same swarm. Parsed from `HYPERHIVE_PEERS`.
|
||||
#[derive(Debug, Clone, serde::Deserialize)]
|
||||
pub struct PeerHive {
|
||||
pub label: String,
|
||||
pub domain: String,
|
||||
pub cert_fingerprint: Option<String>,
|
||||
}
|
||||
|
||||
/// Peer hives in the same swarm, parsed from `HYPERHIVE_PEERS` env var
|
||||
/// (JSON array of `{label,domain}` objects, emitted by the c0re NixOS
|
||||
/// module from `services.hyperhive.peers`). Returns empty vec on
|
||||
/// single-hive deploys (env var absent).
|
||||
/// (JSON array of `{domain, cert_fingerprint}` objects, emitted by the
|
||||
/// c0re NixOS module from `services.hyperhive.swarm.peers`). Returns
|
||||
/// empty vec on single-hive deploys (env var absent).
|
||||
#[must_use]
|
||||
pub fn peers() -> Vec<PeerHive> {
|
||||
env::var("HYPERHIVE_PEERS")
|
||||
|
|
|
|||
|
|
@ -267,19 +267,14 @@ struct StateSnapshot {
|
|||
/// unset — chrome omits the swarm segment of the breadcrumb.
|
||||
swarm_name: Option<String>,
|
||||
/// Peer hives in the same swarm. Parsed from `HYPERHIVE_PEERS`
|
||||
/// (JSON array of `{label,domain}` objects, emitted by the c0re
|
||||
/// NixOS module from `services.hyperhive.peers`). Empty on
|
||||
/// single-hive deploys. Feeds the P33RS dashboard tab. Each entry
|
||||
/// exposes `name` (the operator-chosen label) and `url` (dashboard
|
||||
/// link derived as `http://<domain>/`; HTTP-only until the gateway
|
||||
/// has TLS and the scheme is threaded through).
|
||||
/// (JSON array of `{domain,cert_fingerprint}` objects, emitted by
|
||||
/// the c0re NixOS module from `services.hyperhive.swarm.peers`).
|
||||
/// Empty on single-hive deploys. Feeds the P33RS dashboard tab.
|
||||
peer_hives: Vec<PeerHiveView>,
|
||||
}
|
||||
|
||||
/// One peer hive for the P33RS dashboard tab. Derived from
|
||||
/// `HYPERHIVE_PEERS` env; `url` is the peer's dashboard root so the
|
||||
/// tab can render a clickable card without knowing the remote port.
|
||||
/// HTTP-only until per-peer TLS is wired through the gateway layer.
|
||||
/// `HYPERHIVE_PEERS` env; `url` is the peer's HTTPS dashboard root.
|
||||
#[derive(Serialize)]
|
||||
struct PeerHiveView {
|
||||
name: String,
|
||||
|
|
@ -498,15 +493,16 @@ async fn api_state(headers: HeaderMap, State(state): State<AppState>) -> axum::J
|
|||
}
|
||||
|
||||
/// Parse `HYPERHIVE_PEERS` env var into dashboard-ready `PeerHiveView`
|
||||
/// entries. The env var is a JSON array of `{label, domain}` objects
|
||||
/// emitted by the c0re NixOS module from `services.hyperhive.peers`.
|
||||
/// Each entry becomes `{ name: label, url: "http://domain/" }` for the
|
||||
/// P33RS tab. Returns empty vec when unset (single-hive deploy).
|
||||
/// entries. The env var is a JSON array of `{domain, cert_fingerprint}`
|
||||
/// objects emitted by the c0re NixOS module from
|
||||
/// `services.hyperhive.swarm.peers`. Each entry becomes
|
||||
/// `{ name: domain, url: "https://domain/" }` for the P33RS tab.
|
||||
/// Returns empty vec when unset (single-hive deploy).
|
||||
fn parse_peer_hives() -> Vec<PeerHiveView> {
|
||||
#[derive(serde::Deserialize)]
|
||||
struct Raw {
|
||||
label: String,
|
||||
domain: String,
|
||||
cert_fingerprint: Option<String>,
|
||||
}
|
||||
let Ok(json) = std::env::var("HYPERHIVE_PEERS") else {
|
||||
return Vec::new();
|
||||
|
|
@ -517,8 +513,8 @@ fn parse_peer_hives() -> Vec<PeerHiveView> {
|
|||
};
|
||||
raw.into_iter()
|
||||
.map(|r| PeerHiveView {
|
||||
name: r.label,
|
||||
url: format!("http://{}/", r.domain),
|
||||
name: r.domain.clone(),
|
||||
url: format!("https://{}/", r.domain),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,48 +99,31 @@ in
|
|||
# containers via `meta.rs::FORWARDED_VARS`. Consumed by
|
||||
# `identity.rs::peers()` + the dashboard's `peer_hives` state field
|
||||
# (feeds the P33RS dashboard tab).
|
||||
options.services.hyperhive.peers = lib.mkOption {
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "lab.example.com";
|
||||
description = ''
|
||||
DNS domain of the peer hive. Used to construct the peer's
|
||||
dashboard URL (`http://''${domain}/`) and for Matrix
|
||||
federation auto-discovery (`matrix.''${domain}`).
|
||||
Must be reachable from this host.
|
||||
'';
|
||||
};
|
||||
tlsCertFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
Optional path to a PEM cert/bundle to trust for this peer's
|
||||
TLS. Null = system CA bundle (for Let's Encrypt peers). Set
|
||||
to the peer's self-signed cert for `selfSignedTls = true`
|
||||
peers. Forward-compat slot; not yet used in v0.
|
||||
'';
|
||||
};
|
||||
options.services.hyperhive.swarm.peers = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule {
|
||||
options = {
|
||||
certFingerprint = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "sha256:abc123...";
|
||||
description = ''
|
||||
Expected TLS certificate fingerprint for this peer's HTTPS
|
||||
endpoint. Null = trust the system CA bundle (for Let's
|
||||
Encrypt peers). Set to pin a self-signed cert.
|
||||
'';
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
example = {
|
||||
lab = {
|
||||
domain = "lab.example.com";
|
||||
};
|
||||
edge = {
|
||||
domain = "edge.corp";
|
||||
};
|
||||
"lab.example.com" = { certFingerprint = "sha256:abc123"; };
|
||||
"edge.corp" = { };
|
||||
};
|
||||
description = ''
|
||||
Peer hives in the same swarm. The attrset key is a short label
|
||||
used in dashboard links and log messages -- it does not need to
|
||||
match the remote hive's `hiveName`. Null `tlsCertFile` uses the
|
||||
system CA bundle; set it for self-signed TLS peers (forward-compat
|
||||
slot, not yet used in v0).
|
||||
Peer hives in the same swarm. The attrset key is the peer's DNS
|
||||
domain — used for dashboard links and Matrix federation discovery.
|
||||
Null `certFingerprint` trusts the system CA bundle; set it to pin
|
||||
a self-signed TLS cert.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -365,16 +348,16 @@ in
|
|||
# falls back to `<hostname>:3000`.
|
||||
HIVE_FORGE_PUBLIC_URL = "https://${config.services.hyperhive.forge.domain}";
|
||||
}
|
||||
// lib.optionalAttrs (config.services.hyperhive.peers != { }) {
|
||||
# Peer hives serialised as a JSON array of {label, domain} objects.
|
||||
# Consumed by hive-ag3nt::identity::peers() + the dashboard's
|
||||
# peer_hives StateSnapshot field (P33RS tab). tlsCertFile is
|
||||
# nix-side-only (host nginx/trust config); rust never needs the path.
|
||||
// lib.optionalAttrs (config.services.hyperhive.swarm.peers != { }) {
|
||||
# Peer hives serialised as a JSON array of {domain, cert_fingerprint}
|
||||
# objects. Consumed by hive-ag3nt::identity::peers() + the dashboard's
|
||||
# peer_hives StateSnapshot field (P33RS tab). Domain is the attrset key;
|
||||
# cert_fingerprint is null for CA-trusted peers.
|
||||
HYPERHIVE_PEERS = builtins.toJSON (
|
||||
lib.mapAttrsToList (label: p: {
|
||||
inherit label;
|
||||
inherit (p) domain;
|
||||
}) config.services.hyperhive.peers
|
||||
lib.mapAttrsToList (domain: p: {
|
||||
inherit domain;
|
||||
cert_fingerprint = p.certFingerprint;
|
||||
}) config.services.hyperhive.swarm.peers
|
||||
);
|
||||
};
|
||||
serviceConfig = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue