The swarm always has exactly one queue; a hive can only lack its address. Reworded every prose site this PR added that stated or implied the opposite, to name what is actually absent (coordinates, credential, or address) instead of the queue itself. Refs #3805
97 lines
4.2 KiB
Nix
97 lines
4.2 KiB
Nix
# Swarm-queue coordinates for this agent's harness.
|
|
#
|
|
# Three of the four the harness needs are addresses (this file's two options
|
|
# plus the secret's path); the fourth, the client id, arrives as a file beside
|
|
# the secret so a reader never spells `hive-<name>-agent` a second time.
|
|
#
|
|
# ⚠️ The credential arrives as a systemd credential and NOT as a bind mount,
|
|
# and the mode is why: the host file is `root:0600` and this unit runs as the
|
|
# unprivileged agent user. nspawn's `--load-credential` (written by
|
|
# `hive_c0re::lifecycle::host_config`) is read by the container manager as
|
|
# root and re-exposed under this unit's own `User=`; a bind would deliver a
|
|
# file the harness cannot open.
|
|
{
|
|
lib,
|
|
config,
|
|
...
|
|
}:
|
|
let
|
|
cfg = config.hyperhive.queue;
|
|
configured = cfg.natsUrl != null && cfg.tokenEndpoint != null;
|
|
|
|
# The two ids `hive_c0re::lifecycle::host_config` forwards under. Neither
|
|
# side can discover the other's spelling, so a rename is a rename there too.
|
|
secretCredential = "hive-queue-agent-secret";
|
|
clientIdCredential = "hive-queue-agent-client-id";
|
|
in
|
|
{
|
|
options.hyperhive.queue = {
|
|
natsUrl = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
example = "nats://10.42.0.1:4222";
|
|
description = ''
|
|
Where the swarm queue listens, as this container reaches it.
|
|
|
|
Set by the generated meta flake from the host's
|
|
{option}`services.hyperhive.deploy.hive-controller.queue.agentNatsUrl`,
|
|
which is the bridge address rather than a loopback one — inside this
|
|
container `127.0.0.1` is the agent itself.
|
|
|
|
`null` means this hive has not been given the queue's address for its
|
|
agents, and the harness then declares no credential and logs that it
|
|
has none. It is deliberately not defaulted to anything: a guessed
|
|
address builds fine and talks to the wrong machine.
|
|
'';
|
|
};
|
|
|
|
tokenEndpoint = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
example = "https://auth.example.com/api/oidc/token";
|
|
description = ''
|
|
The swarm IdP's OAuth2 token endpoint. The harness mints a
|
|
`client_credentials` token there and presents it to the queue, which
|
|
authenticates it as the client named in the delivered credential.
|
|
|
|
Set together with {option}`hyperhive.queue.natsUrl` or not at all —
|
|
the harness treats a half-set pair as a deployment bug rather than as
|
|
"no queue coordinates".
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf configured {
|
|
systemd.services.hive-agent = {
|
|
# Bare ids, no paths: this is the terse `LoadCredential=` form that
|
|
# inherits a credential the service *manager* received, which is what
|
|
# the container manager passed in. `man systemd.exec` also makes that
|
|
# form non-fatal when the credential is absent, which is exactly the
|
|
# behaviour a hive whose publisher has not run yet needs — the unit
|
|
# starts, finds no id, and says so.
|
|
serviceConfig.LoadCredential = [
|
|
secretCredential
|
|
clientIdCredential
|
|
];
|
|
environment = {
|
|
# `%d` is `$CREDENTIALS_DIRECTORY`, per-unit and owned by `User=`.
|
|
# Same shape hive-c0re's own queue client is handed its secret in
|
|
# (`nix/host-modules/hive-c0re/environment.nix`) — the harness reads
|
|
# a path and never a value.
|
|
HIVE_AGENT_OIDC_CLIENT_SECRET_FILE = "%d/${secretCredential}";
|
|
# The id is public (it is sent to the token endpoint on every
|
|
# connection) but still arrives as a path, because it arrives *with*
|
|
# the secret. `QueueConfig::from_env` wants it as a value, so the
|
|
# harness reads this file itself — see `hive-agent`'s `swarm_queue`.
|
|
HIVE_AGENT_OIDC_CLIENT_ID_FILE = "%d/${clientIdCredential}";
|
|
};
|
|
# No `HIVE_AGENT_OIDC_CA_FILE`. The hive's own client needs one because
|
|
# the host does not trust the swarm's CA, but an agent does: the meta
|
|
# flake embeds the hive CA and the swarm root it is issued under into
|
|
# this container's `security.pki.certificateFiles` at build time, and
|
|
# reqwest's rustls backend verifies against the system store. A path
|
|
# here would need the bundle delivered as a third credential to say
|
|
# nothing new.
|
|
};
|
|
};
|
|
}
|