swarm options: no swarm.* value depends on a deploy option or this host's hive
- swarm.serviceDomains lists every swarm service name on every host. The
store's issuing role is built from it, so the store now admits a leaf
for grafana, metrics, otel, logs, the bao UI and the apex whichever host
runs the store. Each gateway's own leaf stays narrowed by
localServiceDomains.
- swarm.matrix.apiUrl defaults to http://<swarm.matrix.gatewayHost>
(null when gatewayHost is null) instead of loopback on the matrix host.
- The authelia vhost proxies /bridge/ to swarm-authelia-bridge with the
prefix stripped, and deploy.swarm-controller.authBridgeUrl defaults to
${swarm.authelia.url}/bridge on every host. swarm.authelia.bridgeUrl is
removed.
- swarm-authelia-bridge admits only swarm-controller's OIDC client on
every request (403 for any other active token), configured by
SWARM_AUTHELIA_BRIDGE_CONTROLLER_CLIENT_ID (renamed from
..._OPERATOR_READER_CLIENT_ID, which gated ListOperators alone).
- swarm.peerHives is removed; swarm-wireguard.nix filters this host's own
hive out of swarm.hives itself.
Closes #4933
This commit is contained in:
parent
207b089498
commit
bed4358e19
21 changed files with 226 additions and 283 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# The swarm's directory: one entry per hive, **including this one**,
|
||||
# identical on every host in the swarm. `services.hyperhive.hiveName`
|
||||
# says which entry is us, and `peerHives` below derives the rest.
|
||||
# says which entry is us.
|
||||
#
|
||||
# Why a directory rather than a per-host peer list: every field here is
|
||||
# intrinsic to the hive it describes — none of them says anything about
|
||||
|
|
@ -78,41 +78,31 @@ let
|
|||
# assertion encoded an intended shape, not a property of the code, and
|
||||
# it rejected the supported migration path: a hive pinning its old
|
||||
# `forge.<hive domain>` while joining a swarm at a different apex.
|
||||
#
|
||||
# Every name is listed whether or not this host runs the service: the
|
||||
# store's issuing role is built from this list on the store's host and
|
||||
# has to admit a leaf for any gateway in the swarm. What one gateway's
|
||||
# leaf carries is `localServiceDomains`.
|
||||
#
|
||||
# Membership is also what `gateway.lib.tlsFor` consults to pick the
|
||||
# services leaf over the hive one, so a gateway-published swarm name
|
||||
# missing here is served the hive certificate, which cannot cover a name
|
||||
# under a different apex.
|
||||
serviceDomains' = [
|
||||
swarmCfg.forge.domain
|
||||
swarmCfg.matrix.gatewayHost
|
||||
swarmCfg.authelia.domain
|
||||
]
|
||||
# The swarm UI's name is a SIBLING of the other three, not a parent of
|
||||
# them — the apex is as much a name needing a certificate as
|
||||
# `forge.<apex>` is, and no CA in the hierarchy issues for it
|
||||
# implicitly. Left out, its vhost falls back to the hive leaf and the
|
||||
# swarm's front page opens with a name mismatch.
|
||||
++ lib.optional (deployCfg.swarm-ui.enable && swarmCfg.domain != null) swarmCfg.domain
|
||||
# Every swarm service that claims a gateway name belongs here, and
|
||||
# these three were missing it. Membership is what `gateway.lib.tlsFor`
|
||||
# consults to pick the services leaf over the hive one, so a name
|
||||
# absent from this list is served the HIVE certificate — which cannot
|
||||
# cover a name under a different apex however the sub-CA is set up.
|
||||
#
|
||||
# ⚠️ How that stayed invisible: a mismatch a browser shows as a
|
||||
# click-through warning is one a machine client rejects outright. The
|
||||
# metrics UI and store looked fine for as long as only people opened
|
||||
# them; the collector's exporter — same defect, no human in the loop —
|
||||
# failed every POST and dropped the samples.
|
||||
++ lib.optional deployCfg.grafana.enable swarmCfg.grafana.domain
|
||||
++ lib.optional deployCfg.victoriametrics.enable swarmCfg.victoriametrics.domain
|
||||
++ lib.optional deployCfg.swarm-otel.enable swarmCfg.otel.domain
|
||||
# VictoriaLogs' vhost is new (was previously unpublished entirely — see
|
||||
# swarm-victorialogs.nix's file-top comment) and needs the same
|
||||
# membership every gateway-published swarm service needs: absent from
|
||||
# this list, `gateway.lib.tlsFor` falls back to the hive leaf, which
|
||||
# cannot cover a name under a different apex — see the ⚠️ above this
|
||||
# list for what that looked like the last time a name was missed here.
|
||||
++ lib.optional deployCfg.victorialogs.enable swarmCfg.victorialogs.domain
|
||||
# The store's browser UI, not the store: `swarm.bao.domain` is mTLS and
|
||||
# never gets a gateway certificate.
|
||||
++ lib.optional deployCfg.bao.enable swarmCfg.bao.ui.domain;
|
||||
# The swarm UI's apex is a sibling of the other names, not a parent:
|
||||
# no CA in the hierarchy issues for it implicitly.
|
||||
swarmCfg.domain
|
||||
swarmCfg.grafana.domain
|
||||
swarmCfg.victoriametrics.domain
|
||||
swarmCfg.otel.domain
|
||||
swarmCfg.victorialogs.domain
|
||||
# The store's browser UI, not the store: `swarm.bao.domain` is mTLS and
|
||||
# never gets a gateway certificate.
|
||||
swarmCfg.bao.ui.domain
|
||||
];
|
||||
|
||||
# Hives whose entry still carries the removed `certFingerprint`. Scanned
|
||||
# here, at top level, because that is the only place an assertion about a
|
||||
|
|
@ -274,28 +264,17 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
options.services.hyperhive.swarm.peerHives = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified);
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
description = ''
|
||||
Read-only: `hives` minus this host's own entry. Derived once here
|
||||
rather than in each consumer, because "everything that isn't me"
|
||||
is a filter four different modules were re-implementing and only
|
||||
one of them has to be wrong for a hive to peer with itself.
|
||||
'';
|
||||
};
|
||||
|
||||
options.services.hyperhive.swarm.serviceDomains = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
description = ''
|
||||
Read-only: the public hostnames of the swarm's own services, in a
|
||||
stable sorted order. Second derived set alongside `peerHives`, and
|
||||
here for the same reason — the CA that name-constrains these and
|
||||
the leaf that carries them as SANs must agree exactly, and two
|
||||
modules each assembling the list is how they stop agreeing.
|
||||
Read-only: the public hostnames of every swarm service, in a
|
||||
stable sorted order, identical on every host whichever services it
|
||||
runs. Derived once here because the CA that name-constrains these,
|
||||
the store role that issues for them and the leaf that carries them
|
||||
as SANs must agree exactly, and two modules each assembling the
|
||||
list is how they stop agreeing.
|
||||
|
||||
Sorted and deduplicated deliberately: consumers compare this list
|
||||
against what they issued last time to decide whether to re-issue,
|
||||
|
|
@ -326,8 +305,6 @@ in
|
|||
};
|
||||
|
||||
config = {
|
||||
services.hyperhive.swarm.peerHives = lib.filterAttrs (name: _: name != cfg.hiveName) swarmCfg.hives;
|
||||
|
||||
services.hyperhive.swarm.serviceDomains = lib.sort (a: b: a < b) (
|
||||
lib.unique (lib.filter (d: d != null && d != "") serviceDomains')
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue