# `swarm-logs` on this agent's PATH, configured for this swarm's log store. # # The binary reads its coordinates from the environment and defaults nothing # (see `swarm-logs/README.md`), so it is installed **wrapped** rather than # bare — the same shape `swarm-controller.nix` installs `swarmctl` in, and for # the same reason: every value here is derived from an option a module owns, # and a default inside the binary would be an address we hope points at # something. # # ⚠️ Gated on the secret store's address as well as on the query URL, because # the identity this CLI presents is the agent's own queue secret, read from the # store with the certificate ./bao.nix keeps. Without a store there is nothing # to authenticate as, and a binary that can only fail would read its 401 as # "no logs". { lib, pkgs, config, ... }: let cfg = config.services.hyperhive.agent.logs; baoCfg = config.services.hyperhive.agent.bao; configured = cfg.queryUrl != null && baoCfg.addr != null; # The same store coordinates ./queue-identity.nix gives the harness, except # the CA: `%d` expands only inside a unit, so it is spelled as the harness # unit's credentials directory, which the agent user's shells can read. # # 🩸 Paths and a name only. A value in `--set` lands in the wrapper script, # which is in the world-readable nix store. wrapperEnv = { HIVE_AGENT_LOGS_QUERY_URL = cfg.queryUrl; HIVE_AGENT_NAME = config.services.hyperhive.agent.user.name; BAO_ADDR = baoCfg.addr; BAO_CLIENT_CERT = baoCfg.clientCertFile; BAO_CLIENT_KEY = baoCfg.clientKeyFile; BAO_CACERT = "/run/credentials/hive-agent.service/hive-agent-bao-server-ca"; }; # Same shape `swarm-controller.nix` wraps `swarmctl` in — `symlinkJoin` + # `wrapProgram`, not a `writeShellScriptBin` shim, because the wrapper has # to leave the binary's `--help`, its exit status and its streams intact. # The whole point of the CLI is that its stdout pipes into `grep`. swarmLogsConfigured = pkgs.symlinkJoin { name = "swarm-logs-configured"; paths = [ config.services.hyperhive.agent.packages.swarm-logs ]; nativeBuildInputs = [ pkgs.makeWrapper ]; postBuild = '' wrapProgram $out/bin/swarm-logs ${ lib.concatStringsSep " " ( lib.mapAttrsToList (name: value: "--set ${name} ${lib.escapeShellArg value}") wrapperEnv ) } ''; }; in { options.services.hyperhive.agent.logs = { queryUrl = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; example = "https://logs.example.com/select/logsql/query"; description = '' The swarm log store's LogsQL query endpoint, as this container reaches it — the machine route `swarm-victorialogs.nix` puts on the gateway, not the browser one at `/`. Set by the generated meta flake from the host's own {option}`services.hyperhive.swarm.victorialogs.domain`. `null` means this hive has not been given the log store's address for its agents, and `swarm-logs` is then not installed at all. Deliberately not defaulted: a guessed address resolves cleanly to the wrong place. ''; }; }; config = lib.mkIf configured { environment.systemPackages = [ swarmLogsConfigured ]; }; }