The one move where the suffix grep is the wrong instrument. There are two otel options a word apart — `swarm.otel.enable` (one per swarm) and `otel.enable` (one per hive, every hive runs it) — so `\.otel\.enable` matches twenty-five references of which most must not change. The module already carries a comment warning about exactly this, on a line that names `swarm.otel` in full rather than through a binding. Triaged by hand and confirmed the other way round: after the move, a grep for the per-hive option still finds it in the files that should keep it. Also worth recording what the alias sweep cannot do. `swarm.nix` reads this as `swarmCfg.otel.enable`, where `swarmCfg = cfg.swarm` and `cfg = config.services.hyperhive` — an alias bound to an alias, two hops from the option path. No syntactic sweep resolves that chain, which is why the module system's own evaluation is the only complete check here and the static sweeps are a way to narrow the work, not to finish it.
95 lines
4.4 KiB
Nix
95 lines
4.4 KiB
Nix
# "The swarm-wide services run HERE."
|
|
#
|
|
# A swarm has one forge, one matrix, one SSO. This says this host is
|
|
# where they live, and asserts the per-service `enable`s that follow —
|
|
# the same mode-not-default shape as ./local-defaults.nix, one tier down.
|
|
#
|
|
# Only the *optional* services derive: matrix and authelia. The forge has
|
|
# no `enable` to assert, because it is not optional — it is the canonical
|
|
# store for the meta flake and every agent's config repo, so it deploys
|
|
# with hyperhive itself.
|
|
{
|
|
lib,
|
|
config,
|
|
...
|
|
}:
|
|
let
|
|
swarmCfg = config.services.hyperhive.swarm;
|
|
in
|
|
{
|
|
options.services.hyperhive.swarm.enableRequiredServices = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
example = true;
|
|
description = ''
|
|
Host the swarm's shared services on this hive. The services that
|
|
exist once per swarm rather than once per hive and are *optional*
|
|
— the matrix homeserver, the SSO provider, the queue, the metrics
|
|
and log stores — have their toggle asserted from this, so a
|
|
swarm's service host is declared in one place.
|
|
|
|
Those toggles live in two namespaces and the split is deliberate:
|
|
{option}`services.hyperhive.deploy.*` for "does THIS host run it",
|
|
`swarm.*.enable` for the ones not yet moved. See ./deploy.nix.
|
|
|
|
The forge is swarm-wide too but has nothing to assert: it is the
|
|
canonical store for the meta flake and every agent's config repo,
|
|
so it deploys with hyperhive itself and is not optional.
|
|
|
|
`services.hyperhive.enableAllLocalDefaults` turns this on as part
|
|
of the all-on-one-box mode. Set it directly to run the swarm's
|
|
services on a host that is not otherwise all-local — a dedicated
|
|
services box with hives elsewhere is exactly that shape.
|
|
|
|
With it off, this hive is a *client* of those services: it still
|
|
configures how to reach them, it just doesn't run them.
|
|
'';
|
|
};
|
|
|
|
# Same precedence reasoning as ./local-defaults.nix: fills in for an
|
|
# operator who hasn't spoken, yields to one who has.
|
|
config.services.hyperhive.swarm = {
|
|
# The last one still spelled `swarm.*.enable`. Everything else that
|
|
# used to derive here — the queue, the SSO provider, the collector,
|
|
# the metrics pair, the log store — now derives below under
|
|
# `deploy.*`, because "does THIS host run it" is a per-host decision
|
|
# and `swarm.*` has to be identical on every host. Same switch, same
|
|
# rule, different attribute path.
|
|
matrix.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
|
};
|
|
|
|
# The collector that feeds the pair above (note: no `swarm.` prefix,
|
|
# this is ./otel.nix's existing per-hive option).
|
|
config.services.hyperhive.otel.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
|
|
|
# The rest of the shared services, deriving from the same switch as the
|
|
# `swarm.*` ones above. They read differently only because "does THIS
|
|
# host run it" lives in `deploy.*` (./deploy.nix) — `swarm.*` has to be
|
|
# identical on every host, and these are exactly the values that must
|
|
# differ.
|
|
#
|
|
# authelia: a swarm has one SSO provider, and this says it lives here.
|
|
# With it off the hive is a *client* — `swarm.authelia.url` still points
|
|
# at whoever runs it.
|
|
config.services.hyperhive.deploy.authelia = lib.mkDefault swarmCfg.enableRequiredServices;
|
|
|
|
# The queue. Same rule: once per swarm, optional.
|
|
config.services.hyperhive.deploy.nats = lib.mkDefault swarmCfg.enableRequiredServices;
|
|
|
|
# The swarm collector that feeds the metrics pair, and the only tier
|
|
# holding the upstream credential. ⚠️ NOT the per-hive collector below,
|
|
# which every hive runs.
|
|
config.services.hyperhive.deploy.otel = lib.mkDefault swarmCfg.enableRequiredServices;
|
|
|
|
# The metrics pair, deriving together on purpose: a store with no UI is
|
|
# unreadable and a UI with no store is empty, so there is no sensible
|
|
# deployment that takes one and not the other from this switch. An
|
|
# operator who wants exactly one still sets it directly, which
|
|
# `mkDefault` allows.
|
|
config.services.hyperhive.deploy.victoriametrics = lib.mkDefault swarmCfg.enableRequiredServices;
|
|
config.services.hyperhive.deploy.grafana = lib.mkDefault swarmCfg.enableRequiredServices;
|
|
|
|
# The log store, from the same switch for the same reason as the rest: a
|
|
# hive that is not the service host is a *client* of it, not a second one.
|
|
config.services.hyperhive.deploy.victorialogs = lib.mkDefault swarmCfg.enableRequiredServices;
|
|
}
|