Watch
0
0
Fork
You've already forked hyperhive
0

hive-forge, hive-matrix: forward each container's journal to the swarm collector

Each container now runs the journal forwarder the CI runner's, Grafana's and
the log store's containers run, pushing to a receiver of its own on the swarm
collector (serviceProducers hive-forge and hive-matrix). Each authenticates as
a new machine OIDC client of its own (swarm.forge.otel.clientId,
swarm.matrix.otel.clientId), registered by a glue file wherever authelia runs,
minted by authelia and published to the store by the secret publisher. The
forge's and the homeserver's browser login clients are unchanged. The client
ids are swarm-forge-collector and swarm-matrix-collector, not
hive-<x>-collector, which is the client id a hive named <x>-collector gets.

The fetch unit inside each container reads the client secret with the store
identity the host already holds for that service. The forge publisher's leaf
is handed into the forge container as an nspawn system credential, as the
grafana and log store containers do. matrix-ctl's leaf is already bound into
the homeserver's container, so its forwarder reads it at those paths, as
swarm-matrix-appservice-publish does; with no matrix-ctl identity the
homeserver's forwarder is off. Each of the two policies gains one read stanza
on its forwarder's client path. The host units that use those identities are
unchanged.

The two containers drop --link-journal=host, and the host collector stops
reading them.
This commit is contained in:
atlas 2026-10-16 11:48:22 +02:00 • committed by mara
commit ce44b6e77e
18 changed files with 511 additions and 134 deletions

View file

@ -547,7 +547,7 @@ let
matrixCtlPolicyName = "swarm-matrix-ctl";
matrixCtlCn = baoDeploy.matrixCtlCommonName;
# Two paths, each spelled to the leaf, and every narrowing in them is
# Three paths, each spelled to the leaf, and every narrowing in them is
# load-bearing.
#
# `secret/data/` is KV v2's ACL prefix, inserted by the engine rather than
@ -563,12 +563,15 @@ let
#
# The second is the homeserver's own OIDC client secret, read-only:
# `swarm-bao-matrix-oidc` on the homeserver's host reads it under this leaf.
# The third, also read-only, is the client secret of the journal forwarder in
# the homeserver's container.
matrixCtlPolicyText = ''
path "${credentialMountPath}/data/${swarmAppserviceTokenLeaf}" {
capabilities = ["create", "update", "read"]
}
''
+ readStanza "${credentialMountPath}/data/swarm/services/${hyperhiveCfg.swarm.matrix.sso.clientId}/oidc/client";
+ readStanza "${credentialMountPath}/data/swarm/services/${hyperhiveCfg.swarm.matrix.sso.clientId}/oidc/client"
+ readStanza "${credentialMountPath}/data/swarm/services/${hyperhiveCfg.swarm.matrix.otel.clientId}/oidc/client";
# The swarm appservice token's leaf, the nix half of
# `swarm_secret_client::matrix::swarm_appservice_token_path`. Under
@ -1103,8 +1106,9 @@ let
# The forge host's one store identity. `swarm-bao-forge-publisher` writes
# the controller's forge token under it, the one writer of that path and
# write-only: it copies a file in and never reads one back.
# `swarm-bao-forge-oidc` reads the forge's own OIDC client secret, that one
# leaf and no other service's.
# `swarm-bao-forge-oidc` reads the forge's own OIDC client secret, and the
# journal forwarder in its container its own, those two leaves and no other
# service's.
forgePublisherWriters = [
{
name = "swarm-forge-publisher";
@ -1114,7 +1118,9 @@ let
capabilities = ["create", "update"]
}
''
+ readStanza "${credentialMountPath}/data/swarm/services/${hyperhiveCfg.swarm.forge.sso.clientId}/oidc/client";
+ readStanza "${credentialMountPath}/data/swarm/services/${hyperhiveCfg.swarm.forge.sso.clientId}/oidc/client"
# The journal forwarder in the forge's container, under this same leaf.
+ readStanza "${credentialMountPath}/data/swarm/services/${hyperhiveCfg.swarm.forge.otel.clientId}/oidc/client";
}
];
@ -1754,9 +1760,11 @@ in
identity the matrix container's `swarm-matrix-appservice-publish`
unit presents when it publishes the swarm appservice's token.
A **third** identity rather than reuse of either sibling above, and
the narrowest of the three: its grant is one path, that
credential itself. The point of the whole arrangement is that the
A **third** identity rather than reuse of either sibling above. Its
grant is that credential itself, plus read on two OIDC client
secrets: the homeserver's, fetched by `swarm-bao-matrix-oidc`, and
that of the journal forwarder in the homeserver's container. The
point of the whole arrangement is that the
process holding the appservice token is not the hive, so handing it
the hive's own leaf — which reads every agent credential in the swarm
and this hive's own secrets — would give the separation away in one
@ -2003,10 +2011,11 @@ in
Subject the store's `swarm-forge-publisher` cert-auth role accepts: the
forge host's one store identity, presented by `swarm-bao-forge-publisher`,
which publishes the swarm-controller's forge token, and by
`swarm-bao-forge-oidc`, which fetches the forge's OIDC client secret.
Its grant is two paths: `swarm/controller/swarm-controller/forge/token`,
write only, and `swarm/services/<forge client id>/oidc/client`, read
only.
`swarm-bao-forge-oidc`, which fetches the forge's OIDC client secret,
and by the journal forwarder in the forge's container. Its grant is
three paths: `swarm/controller/swarm-controller/forge/token`, write
only, and `swarm/services/<forge client id>/oidc/client` and
`swarm/services/<forge forwarder client id>/oidc/client`, read only.
⚠️ Reserved as a hive name by ./swarm.nix, like its siblings.
'';