# The binary cache the swarm pushes agent closures to, as every host sees it: # which attic server, and which cache on it. Both default to the swarm's own, # which the host that sets `deploy.attic.enable` runs (./swarm-attic.nix); an # operator with an instance outside the swarm overrides both. { lib, config, ... }: let swarmDomain = config.services.hyperhive.swarm.domain; # Total on a null swarm domain, as every sibling module is: the # required-domain assertion in hive-network.nix is what an operator should # see, not a coercion error from here. domainBase = if swarmDomain == null then "invalid" else swarmDomain; in { options.services.hyperhive.swarm.attic = { otel.clientId = lib.mkOption { type = lib.types.str; readOnly = true; default = "swarm-attic-collector"; description = '' OAuth2 client id the journal forwarder inside the cache's container authenticates as, and the audience it asks its token for. Read-only because three hosts have to agree on it: authelia registers the client (`glue-attic-otel-oidc-client.nix`), the swarm collector admits it on the container's receiver (`swarm.otel.serviceProducers`), and authelia's mint stores its secret in the store. ''; }; ownDomain = lib.mkOption { type = lib.types.str; readOnly = true; default = "attic.${domainBase}"; defaultText = lib.literalExpression ''"attic.''${services.hyperhive.swarm.domain}"''; description = '' Read-only: the name the swarm's own cache is served under, which {option}`services.hyperhive.swarm.attic.domain` defaults to. A sibling of the swarm's other service names, so the swarm-services sub-CA can issue for it, and in `swarm.serviceDomains` on every host whether or not one runs it. ''; }; domain = lib.mkOption { type = lib.types.nullOr lib.types.str; default = config.services.hyperhive.swarm.attic.ownDomain; defaultText = lib.literalExpression "services.hyperhive.swarm.attic.ownDomain"; example = "cache.example.org"; description = '' Name of the attic server, with no scheme: the swarm builder pushes to `https://`, and trusts the certificate the system roots do, so a Let's Encrypt certificate works and none is pinned. Set together with {option}`services.hyperhive.swarm.attic.cache`; evaluation fails when only one is set. Defaults to the swarm's own cache, the same on every host. For a cache outside the swarm, override both options and leave {option}`services.hyperhive.deploy.attic.enable` unset. With no cache behind the default, a push fails and the closure record says it is not cached. Null pushes nothing: the swarm builder does not push, and the closure record says it is not cached. The push token is not an option. It is at `secret/swarm/services/attic/push-token` in the swarm secret store (field `value`), and the builder reads it on every push. The swarm's own cache creates it; for an external cache the operator writes it. ''; }; cache = lib.mkOption { # attic's own rule for a cache name; the builder checks the same at start. type = lib.types.nullOr (lib.types.strMatching "^[A-Za-z0-9][A-Za-z0-9_+-]{0,49}$"); default = "swarm"; example = "grid"; description = '' Name of the cache on {option}`services.hyperhive.swarm.attic.domain` that the swarm builder pushes closures to, the swarm's own cache by default. The push token must be allowed to push to it. The name follows attic's rule: 1 to 50 letters, digits, `-`, `_` or `+`, starting with a letter or digit. ''; }; }; }