# Swarm peering: who the peer hives are. Serialised into hive-c0re's # environment (HYPERHIVE_PEERS / HIVE_PEER_CA_PATHS — see ./hive-c0re) # and consumed by identity.rs + the dashboard's P33RS tab. # # Declaration only — this module has no `config` block. The mesh that # uses the `wireguard*` fields below lives in ./swarm-wireguard.nix, # because bringing up an interface is host networking rather than swarm # bookkeeping, and a host that runs no hive still needs it. { lib, config, ... }: { # Peer hives in the same swarm. Each entry declares a remote hive # reachable from this host. 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:b1946ac92492d2347c6235b4d2611184a3f5b6cae6c19d6e3c2f0a8e7d4c9f12"; 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. Format: the literal `sha256:` followed by exactly 64 hex digits (case-insensitive, no colon separators) — the SHA-256 digest of the peer's DER-encoded leaf certificate. Generate with `openssl x509 -noout -fingerprint -sha256`, then strip the colons and prepend `sha256:`. A malformed value is ignored with a warning rather than weakening trust. See docs/swarm.md for the full recipe. Scopes only to hive-c0re's own peer HTTPS checks — it does NOT help Matrix federation (tuwunel validates against its container trust bundle). For a self-signed peer whose root CA you want trusted hive-wide (every agent + Matrix federation), set `caCert` below. ''; }; caCert = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; example = "./peers/edge-ca.pem"; description = '' Path to this peer hive's root CA certificate (PEM). When set, the CA is embedded (at build time, into the nix store — no runtime file on the host) and trusted **everywhere the hive's own internal CA is**: it rides alongside `hive-ca.pem` in each agent's `security.pki.certificateFiles` (via the meta-flake renderer), and is added to the Matrix homeserver container's trust bundle so tuwunel validates *federation* TLS from a self-signed peer hive whose cert chains to it. This is the CA-trust path that `certFingerprint` (leaf-pinning, c0re-only) can't cover, and is what unblocks Matrix federation with a self-signed peer hive. Trust stays inside the hive (agents + the Matrix container), never the host system trust store. Mutually complementary with `certFingerprint`; set `caCert` for the federation case. See docs/swarm.md. ''; }; wireguardPublicKey = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; example = "base64pubkey="; description = '' WireGuard public key for this peer host. Required when `services.hyperhive.swarm.wireguard.enable = true` and you want this peer reachable over the mesh. Null = TLS- only peering (public internet, no mesh tunnel). ''; }; wireguardEndpoint = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; example = "203.0.113.1:51820"; description = '' WireGuard endpoint for this peer in `host:port` form. Required when the peer host is behind a firewall and this host needs to initiate the tunnel. Null = this host waits for the peer to connect (peer-initiates; peer must have an endpoint pointing back at this host). ''; }; wireguardAddress = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; example = "10.100.0.2/32"; description = '' IP address (with prefix) of the peer host on the WireGuard mesh. Used as the `allowedIPs` for the peer's WireGuard config entry and injected into `HYPERHIVE_PEERS` so hive-c0re can route intra-swarm traffic to the mesh address rather than the public domain. Required to include the peer in the WireGuard mesh (peers missing this field are silently excluded from `wg-hive`). ''; }; }; } ); default = { }; example = { "lab.example.com" = { certFingerprint = "sha256:b1946ac92492d2347c6235b4d2611184a3f5b6cae6c19d6e3c2f0a8e7d4c9f12"; }; "edge.corp" = { }; }; description = '' 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. Add `wireguardPublicKey` + `wireguardAddress` (and optionally `wireguardEndpoint`) to include the peer in the WireGuard mesh when `swarm.wireguard.enable = true`. ''; }; options.services.hyperhive.swarm.snapshotStore = { address = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; example = "10.100.0.1"; description = '' Mesh address of the swarm's snapshot store — the single `btrfs receive` endpoint every hive in this swarm pushes agent snapshots to. Bare IP, no prefix. There is exactly **one** store per swarm, not one per peer: the receiver keys destinations by *agent*, so an agent that migrates between hives keeps a single unbroken incremental chain. Per-hive stores would split that chain in two, which is the case the store exists to serve. Null means this swarm has no store configured, and pushing fails saying so rather than guessing an address. Set it on every hive that pushes; the receiving host separately sets `services.hyperhive.snapshotStore.enable`. ''; }; port = lib.mkOption { type = lib.types.port; default = 51821; description = '' TCP port the swarm's snapshot store listens on. Must match the receiving host's `services.hyperhive.snapshotStore.port`. Defaulted (unlike `address`) because it is a shared convention both sides read from the same option docs — whereas an address is deployment-specific and cannot be guessed. ''; }; }; }