swarm-builder, swarm-claude-login, swarm-review-classifier: forward each container's journal to the swarm collector
Each container now runs the journal forwarder the queue's container runs, pushing to a receiver of its own on the swarm collector as the service's existing OIDC client, with the client's secret read inside the container by the fetch unit. Their store identities are system credentials, so the fetch unit loads them too. The three containers drop --link-journal=host, which hid their journals from the forwarder, and the host collector stops reading them.
This commit is contained in:
parent
40a2bd047b
commit
a2a94f63c8
10 changed files with 321 additions and 32 deletions
|
|
@ -46,13 +46,32 @@ let
|
|||
unit = "swarm-review-classifier";
|
||||
clientId = hyperhiveCfg.swarm.review-classifier.clientId;
|
||||
|
||||
# The container's journal forwarder pushes to its own receiver on the swarm
|
||||
# collector, the route `serviceProducers.swarm-review-classifier` in
|
||||
# ./swarm-otel-service.nix declares, by the collector's gateway name. The
|
||||
# port suffix is elided on 443, as in ./swarm-bao.nix.
|
||||
swarmOtelCfg = hyperhiveCfg.swarm.otel;
|
||||
gatewayPortSuffix = lib.optionalString (
|
||||
gatewayCfg.httpsPort != 443
|
||||
) ":${toString gatewayCfg.httpsPort}";
|
||||
forwarderEndpoint = "https://${swarmOtelCfg.domain}${gatewayPortSuffix}/${machine}";
|
||||
forwarderUnit = "swarm-journal-forwarder-oidc";
|
||||
# Loopback in the container's own netns, and distinct from the other service
|
||||
# containers' forwarders all the same.
|
||||
forwarderTelemetryPort = 8894;
|
||||
|
||||
# The daemon reaches authelia, the store and the queue by name over TLS, and
|
||||
# in self-signed mode their leaves chain to the hive CA.
|
||||
caTrust = import ./lib/hive-ca-trust.nix { inherit lib tlsCfg gatewayCfg; };
|
||||
caBundleModule = caTrust.trustBundle {
|
||||
inherit pkgs;
|
||||
name = machine;
|
||||
consumers = [ unit ];
|
||||
consumers = [
|
||||
unit
|
||||
# Go: `SSL_CERT_FILE` replaces its trust store, for the swarm
|
||||
# collector's and authelia's names.
|
||||
"opentelemetry-collector"
|
||||
];
|
||||
};
|
||||
|
||||
haveClientIdentity =
|
||||
|
|
@ -72,6 +91,7 @@ let
|
|||
# one word.
|
||||
oneWord = path: builtins.match ".*[[:space:]].*" path == null;
|
||||
credential = id: "/run/credentials/${unit}.service/${id}";
|
||||
forwarderCredential = id: "/run/credentials/${forwarderUnit}.service/${id}";
|
||||
|
||||
# What `claude` exports its metrics with, and the daemon its ACP runs' cost,
|
||||
# where this host runs a hive-tier collector on the bridge. The daemon adds
|
||||
|
|
@ -164,12 +184,9 @@ in
|
|||
autoStart = true;
|
||||
# The daemon keeps no state; its scratch directories are under PrivateTmp.
|
||||
ephemeral = false;
|
||||
# Journal files on the host, not inside the container: nixpkgs hardcodes
|
||||
# --link-journal=try-guest, and EXTRA_NSPAWN_FLAGS expands after it.
|
||||
extraFlags = [
|
||||
"--link-journal=host"
|
||||
]
|
||||
++ lib.mapAttrsToList (id: source: "--load-credential=${id}:${source}") storeFiles;
|
||||
# No `--link-journal=host`: the journal stays in the guest, where the
|
||||
# container's own forwarder reads it (../container-modules/swarm-journal-forwarder.nix).
|
||||
extraFlags = lib.mapAttrsToList (id: source: "--load-credential=${id}:${source}") storeFiles;
|
||||
inherit privateNetwork;
|
||||
hostBridge = networkCfg.bridgeName;
|
||||
bindMounts = caTrust.bindMount;
|
||||
|
|
@ -179,6 +196,7 @@ in
|
|||
{
|
||||
imports = [
|
||||
../container-modules/swarm-container.nix
|
||||
../container-modules/swarm-journal-forwarder.nix
|
||||
caBundleModule
|
||||
];
|
||||
|
||||
|
|
@ -193,6 +211,32 @@ in
|
|||
# nixpkgs, so the host's allowance does not reach here.
|
||||
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ "claude-code" ];
|
||||
|
||||
# Authenticated as the daemon's own OIDC client, whose secret its
|
||||
# store identity already reads: one identity for the whole container.
|
||||
# That identity is a system credential, so the fetch unit loads it
|
||||
# too; the daemon's `LoadCredential` below is that unit's alone.
|
||||
services.hyperhive.swarmJournalForwarder = {
|
||||
enable = true;
|
||||
serviceName = "review-classifier";
|
||||
endpoint = forwarderEndpoint;
|
||||
inherit clientId;
|
||||
tokenUrl = "${autheliaCfg.url}/api/oidc/token";
|
||||
telemetryPort = forwarderTelemetryPort;
|
||||
store = {
|
||||
package = baoDeploy.package;
|
||||
addr = "https://${baoCfg.domain}:${toString baoCfg.port}";
|
||||
secretPath = "secret/swarm/services/${clientId}/oidc/client";
|
||||
clientCertFile = forwarderCredential "review-classifier-bao-cert";
|
||||
clientKeyFile = forwarderCredential "review-classifier-bao-key";
|
||||
caFile =
|
||||
if storeFiles ? review-classifier-bao-server-ca then
|
||||
forwarderCredential "review-classifier-bao-server-ca"
|
||||
else
|
||||
null;
|
||||
};
|
||||
};
|
||||
systemd.services.${forwarderUnit}.serviceConfig.LoadCredential = lib.attrNames storeFiles;
|
||||
|
||||
systemd.services.${unit} = {
|
||||
description = "answer the swarm UI's review try-outs";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
|
|
|||
Loading…
Reference in a new issue