The metrics store's container gets privateNetwork = true with no interface but loopback. VictoriaMetrics listens on unix:/run/swarm-victoriametrics/victoriametrics.sock, a host directory (root:nginx 0770) bind-mounted into the container, and every vhost location that forwarded to 127.0.0.1:8428 now forwards to that socket. The store runs as a static user whose primary group is nginx's gid, with UMask 0007, so the socket it creates is 0770 group nginx. This relies on VictoriaMetrics >= 1.153.0 honouring the umask (the locked nixpkgs ships 1.153.0). nixpkgs' readiness loop curls a TCP URL, so postStart is replaced with the same loop over --unix-socket. swarm.victoriametrics.port is removed (nothing binds it any more), with a mkRemovedOptionModule entry, and dropped from swarm-otel's host port-collision assertion. The container's resolver unit is dropped: there is no interface to reach the bridge resolver through, and the store resolves no names. The collector scrape, the collector push and Grafana's datasource already reach the store by its published domain, so they are unchanged. Refs #4815 Refs #3560
740 lines
32 KiB
Nix
740 lines
32 KiB
Nix
# "What does THIS host deploy?"
|
|
#
|
|
# Separated from `services.hyperhive.swarm.*` because those are two
|
|
# different kinds of fact and only one of them varies per machine:
|
|
#
|
|
# swarm.* — swarm-wide truth. The swarm's name, domain, hives, peers,
|
|
# and where each service lives. **Identical on every
|
|
# host**, byte for byte; a hive needs all of it to be a
|
|
# *client* of the swarm.
|
|
# deploy.* — this machine's deployment decisions. Necessarily different
|
|
# on every host, because that is what a deployment is.
|
|
#
|
|
# The `enable` toggles live here rather than under `swarm.*` so the
|
|
# namespace that is identical everywhere does not carry the one thing
|
|
# that must differ per host.
|
|
#
|
|
# Flat and named for the thing deployed — `deploy.forgejo`, not
|
|
# `deploy.swarmServices.forgejo`: grouping by "swarm service" re-encodes
|
|
# the service-side taxonomy into a layer that does not care about it.
|
|
#
|
|
# ⚠️ Each entry is an attrset with an `enable`, not a bare bool, so a
|
|
# service that grows a second *deployment* decision has somewhere to put
|
|
# it — `deploy.nats = { enable; authPackage; }` is then an ordinary
|
|
# addition rather than a migration, where a bare bool leaves it
|
|
# unrepresentable.
|
|
#
|
|
# ⚠️ The renames below are deliberately in this one file rather than
|
|
# spread across the service modules, so all of them have a single home
|
|
# and a single file to delete when the deprecation window closes — the
|
|
# shape ./swarm-peers-removed.nix already uses.
|
|
{ config, lib, ... }:
|
|
let
|
|
# The swarm UI's own switch, in both spellings. Accepted and ignored: a
|
|
# definition only produces a warning, so a host that still sets one keeps
|
|
# evaluating. `null` is "not set".
|
|
swarmUiSwitchIgnored = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.bool;
|
|
default = null;
|
|
visible = false;
|
|
description = ''
|
|
No effect. swarm-ui runs wherever swarm-controller runs.
|
|
'';
|
|
};
|
|
swarmUiSwitchWarning =
|
|
path: value:
|
|
lib.optional (value != null)
|
|
"services.hyperhive.${path} no longer has any effect: swarm-ui now runs wherever swarm-controller runs. Remove this setting; services.hyperhive.deploy.swarm-controller.enable decides it.";
|
|
|
|
# Shared by the two removed spellings of the status-publishing secret below.
|
|
statusSecretRemoved = ''
|
|
hive-c0re reads this hive's status-publishing client secret from the
|
|
swarm's secret store, under the hive's own certificate
|
|
(deploy.bao.clientCertFile), and swarm-secret-publish on the host that runs
|
|
authelia puts it there. Remove this definition; the file it named is read
|
|
by nothing now and can be deleted.
|
|
'';
|
|
in
|
|
{
|
|
imports = [
|
|
# Same type, same meaning, new path — so a rename carries it exactly
|
|
# and existing configs keep evaluating with one warning naming both
|
|
# paths. Precedent: ./hive-forge/service.nix, ./hive-matrix.nix.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "grafana" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "grafana" "enable" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "grafana" "datasourceUrl" ]
|
|
[ "services" "hyperhive" "deploy" "grafana" "datasourceUrl" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "grafana" "logsDatasourceUrl" ]
|
|
[ "services" "hyperhive" "deploy" "grafana" "logsDatasourceUrl" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "grafana" "plugins" ]
|
|
[ "services" "hyperhive" "deploy" "grafana" "plugins" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "victoriametrics" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "victoriametrics" "enable" ]
|
|
)
|
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "victoriametrics" "port" ] ''
|
|
VictoriaMetrics listens on a unix socket in a network namespace of its
|
|
own, and the gateway reaches it there, so it binds no host port. Remove
|
|
this definition.
|
|
'')
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "victorialogs" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "victorialogs" "enable" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "controller" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "swarm-controller" "enable" ]
|
|
)
|
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "controller" "forgeTokenFile" ] ''
|
|
The controller reads its forge token from the swarm's secret store, under
|
|
its own certificate, and swarm-bao-forge-publisher on the forge's host
|
|
puts it there. Remove this definition; the file it named is read by
|
|
nothing now and can be deleted.
|
|
'')
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "controller" "authBridgeUrl" ]
|
|
[ "services" "hyperhive" "deploy" "swarm-controller" "authBridgeUrl" ]
|
|
)
|
|
(lib.mkRemovedOptionModule
|
|
[ "services" "hyperhive" "swarm" "controller" "queue" "clientSecretFile" ]
|
|
''
|
|
The controller reads its queue client secret from the swarm's secret
|
|
store, under its own certificate (deploy.swarm-controller.baoClientCertFile),
|
|
and swarm-secret-publish on the host that runs authelia puts it there.
|
|
Remove this definition; the file it named is read by nothing now and can
|
|
be deleted.
|
|
''
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "authelia" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "authelia" "enable" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "authelia" "usersFile" ]
|
|
[ "services" "hyperhive" "deploy" "authelia" "usersFile" ]
|
|
)
|
|
# `hostClientSecretDir`, `hostUsersFile` and `grafana.socketDir`
|
|
# deliberately have NO entry here. A rename module contributes a
|
|
# *definition* to its target, and all three are `readOnly`, which refuses a
|
|
# second one — so a shim for any of them makes every evaluation fail with
|
|
# "set multiple times", naming the option's own default as the rival
|
|
# definition.
|
|
#
|
|
# The first two are derived, so nothing could ever have set them and a
|
|
# shim's only customer is a reader of the old path. `grafana.socketDir` was
|
|
# a plain settable option; only a test fixture set it in
|
|
# this tree, but a deployment outside it can have. That setter now fails
|
|
# evaluation with "option does not exist" at the old path, rather than
|
|
# being carried to the new one.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "nats" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "nats" "enable" ]
|
|
)
|
|
# `tokenEndpoint` stays under `swarm.*`: it is the swarm IdP's one
|
|
# address, identical on every hive, where this is "the queue as seen from
|
|
# here".
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "statusPublish" "natsUrl" ]
|
|
[ "services" "hyperhive" "deploy" "hive-controller" "statusPublish" "natsUrl" ]
|
|
)
|
|
(lib.mkRemovedOptionModule [
|
|
"services"
|
|
"hyperhive"
|
|
"swarm"
|
|
"statusPublish"
|
|
"clientSecretFile"
|
|
] statusSecretRemoved)
|
|
(lib.mkRemovedOptionModule [
|
|
"services"
|
|
"hyperhive"
|
|
"deploy"
|
|
"hive-controller"
|
|
"statusPublish"
|
|
"clientSecretFile"
|
|
] statusSecretRemoved)
|
|
# Both old spellings of "run a hive here" forward to the one switch.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "hive-controller" "enable" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "c0re" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "hive-controller" "enable" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "otel" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "swarm-otel" "enable" ]
|
|
)
|
|
# ⚠️ Not to be confused with `services.hyperhive.otel.clientSecretFile`,
|
|
# a different option on the hive tier that is not part of this table. A
|
|
# bare `clientSecretFile` matches five distinct options across the tree.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "otel" "clientSecretFile" ]
|
|
[ "services" "hyperhive" "deploy" "swarm-otel" "clientSecretFile" ]
|
|
)
|
|
|
|
# The runner moved from `deploy.forgejo.ci` to `deploy.ci-runner` with
|
|
# every option keeping its type and meaning, so the old paths forward.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "deploy" "forgejo" "ci" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "enable" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "deploy" "forgejo" "ci" "name" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "name" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "deploy" "forgejo" "ci" "concurrency" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "concurrency" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "deploy" "forgejo" "ci" "labels" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "labels" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "deploy" "forgejo" "ci" "package" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "package" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "deploy" "forgejo" "ci" "jobTimeout" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "jobTimeout" ]
|
|
)
|
|
|
|
# The gateway's services-issuer pair is a swarm-service identity, not a
|
|
# hive's, so it sits with the store's other host-unit readers.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "deploy" "hive-controller" "tls" "baoClientCertFile" ]
|
|
[ "services" "hyperhive" "deploy" "bao" "servicesIssuerClientCertFile" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "deploy" "hive-controller" "tls" "baoClientKeyFile" ]
|
|
[ "services" "hyperhive" "deploy" "bao" "servicesIssuerClientKeyFile" ]
|
|
)
|
|
|
|
# The runner toggle sat under `swarm.forge.ci` before `deploy.forgejo.ci`.
|
|
# Both were per-host, so each forwards straight to its final path.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "forge" "ci" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "enable" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "forge" "ci" "name" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "name" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "forge" "ci" "concurrency" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "concurrency" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "forge" "ci" "labels" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "labels" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "forge" "ci" "package" ]
|
|
[ "services" "hyperhive" "deploy" "ci-runner" "package" ]
|
|
)
|
|
|
|
# The rest of the forge split. What stays under `swarm.forge` is what the
|
|
# forge IS from any hive's point of view — the names and ports it answers
|
|
# on, the URLs it advertises, the client id it is registered under; these
|
|
# four are what the host running it decides. Its package is renamed
|
|
# further down with the other `*.package` entries. `sso` splits
|
|
# because its two halves are different facts: the client id must match the
|
|
# entry in authelia's register, the secret is a path on this machine.
|
|
#
|
|
# `mirrors` renames in one entry rather than one per field: it is a single
|
|
# option of a list-of-submodule type, so the rename carries its whole
|
|
# value.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "forge" "openFirewall" ]
|
|
[ "services" "hyperhive" "deploy" "forgejo" "openFirewall" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "forge" "mirrors" ]
|
|
[ "services" "hyperhive" "deploy" "forgejo" "mirrors" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "forge" "sso" "clientSecretFile" ]
|
|
[ "services" "hyperhive" "deploy" "forgejo" "sso" "clientSecretFile" ]
|
|
)
|
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "forge" "hostSwarmControllerTokenFile" ]
|
|
''
|
|
The forge publishes the swarm-controller's forge token to the swarm
|
|
secret store (swarm-bao-forge-publisher), and the controller reads it
|
|
there. Remove this definition; the file it named is read by nothing now
|
|
and can be deleted.
|
|
''
|
|
)
|
|
|
|
# The homeserver, split the same way. `swarm.matrix` keeps what it IS to
|
|
# every hive — the name it answers to, the ports and URLs it is reached
|
|
# on, the client id it is registered under. These six are what the host
|
|
# running it decides; its two packages are renamed further down with
|
|
# the other `*.package` entries. ⚠️ `enable` is NOT here: its shim lives in
|
|
# ./hive-matrix.nix, so that file is the one
|
|
# to check before assuming this table is the whole matrix story.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "matrix" "openFirewall" ]
|
|
[ "services" "hyperhive" "deploy" "matrix" "openFirewall" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "matrix" "trustedServers" ]
|
|
[ "services" "hyperhive" "deploy" "matrix" "trustedServers" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "matrix" "maxRequestSize" ]
|
|
[ "services" "hyperhive" "deploy" "matrix" "maxRequestSize" ]
|
|
)
|
|
# Both spellings of the registration token, removed rather than renamed:
|
|
# the homeserver does not accept a shared registration secret at all,
|
|
# so there is no path to point a definition at. Accounts are created by
|
|
# the swarm's appservice.
|
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "matrix" "registrationTokenFile" ] ''
|
|
The matrix registration token is gone: swarm-controller creates accounts
|
|
as the swarm's appservice instead, so there is no shared secret for
|
|
tuwunel to check. Remove this definition — nothing needs replacing.
|
|
The old token file at /var/lib/hyperhive/matrix-register-token is read by
|
|
nothing now and can be deleted. See docs/integrations/matrix.md.
|
|
'')
|
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "deploy" "matrix" "registrationTokenFile" ] ''
|
|
The matrix registration token is gone: swarm-controller creates accounts
|
|
as the swarm's appservice instead, so there is no shared secret for
|
|
tuwunel to check. Remove this definition — nothing needs replacing.
|
|
The old token file at /var/lib/hyperhive/matrix-register-token is read by
|
|
nothing now and can be deleted. See docs/integrations/matrix.md.
|
|
'')
|
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "matrix" "gui" "enable" ] ''
|
|
The matrix web client has no on/off switch: every host that runs the
|
|
homeserver serves it at services.hyperhive.swarm.matrix.gatewayHost,
|
|
and the swarm UI links to it. Remove this definition.
|
|
'')
|
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "deploy" "matrix" "gui" "enable" ] ''
|
|
The matrix web client has no on/off switch: every host that runs the
|
|
homeserver serves it at services.hyperhive.swarm.matrix.gatewayHost,
|
|
and the swarm UI links to it. Remove this definition.
|
|
'')
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "matrix" "sso" "clientSecretFile" ]
|
|
[ "services" "hyperhive" "deploy" "matrix" "sso" "clientSecretFile" ]
|
|
)
|
|
|
|
# Retention is read only where the container is defined, so it is a
|
|
# decision of the host running the store rather than something the swarm
|
|
# agrees on. The two stores keep their domain and port in `swarm.*`,
|
|
# because a client hive needs those to reach them; `package` followed
|
|
# `enable` and `retentionPeriod` across in a later slice.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "victoriametrics" "retentionPeriod" ]
|
|
[ "services" "hyperhive" "deploy" "victoriametrics" "retentionPeriod" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "victorialogs" "retentionPeriod" ]
|
|
[ "services" "hyperhive" "deploy" "victorialogs" "retentionPeriod" ]
|
|
)
|
|
|
|
# The switch over all of the above. `allSwarmServices` says whether THIS
|
|
# host runs every service the swarm requires; those services are
|
|
# required of the SWARM, so the name is about the swarm rather than this
|
|
# host's wiring.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "enableRequiredServices" ]
|
|
[ "services" "hyperhive" "deploy" "allSwarmServices" ]
|
|
)
|
|
|
|
# The mode above that one lives under `deploy`, not at the TOP of
|
|
# `services.hyperhive`: that namespace is everything about hyperhive, not
|
|
# the settings of a single hive. `singleHostSwarm` names what the mode
|
|
# asserts — the whole swarm runs on this host — instead of its mechanism.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "enableAllLocalDefaults" ]
|
|
[ "services" "hyperhive" "deploy" "singleHostSwarm" ]
|
|
)
|
|
|
|
# The hive TLS state dir lives under `deploy.hive-controller` (the
|
|
# hive-c0re daemon's namespace), not at the TOP of `services.hyperhive`,
|
|
# which is everything about hyperhive rather than the settings of one hive.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "tls" "stateDir" ]
|
|
[ "services" "hyperhive" "deploy" "hive-controller" "tls" "stateDir" ]
|
|
)
|
|
# The hive CA's lifetime and its leaves', both spellings, removed rather
|
|
# than renamed: no hive CA is generated, and the store's per-hive role
|
|
# sets the gateway leaf's lifetime.
|
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "tls" "caValidityDays" ] ''
|
|
No hive CA is generated any more: the gateway leaf is issued by the
|
|
secret store's pki mount, whose per-hive role sets its lifetime
|
|
(services.hyperhive.deploy.bao.servicesPkiLeafTtlHours). Remove this
|
|
definition. See docs/swarm/ca.md.
|
|
'')
|
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "tls" "leafValidityDays" ] ''
|
|
No hive CA is generated any more: the gateway leaf is issued by the
|
|
secret store's pki mount, whose per-hive role sets its lifetime
|
|
(services.hyperhive.deploy.bao.servicesPkiLeafTtlHours). Remove this
|
|
definition. See docs/swarm/ca.md.
|
|
'')
|
|
(lib.mkRemovedOptionModule
|
|
[ "services" "hyperhive" "deploy" "hive-controller" "tls" "caValidityDays" ]
|
|
''
|
|
No hive CA is generated any more: the gateway leaf is issued by the
|
|
secret store's pki mount, whose per-hive role sets its lifetime
|
|
(services.hyperhive.deploy.bao.servicesPkiLeafTtlHours). Remove this
|
|
definition. See docs/swarm/ca.md.
|
|
''
|
|
)
|
|
(lib.mkRemovedOptionModule
|
|
[ "services" "hyperhive" "deploy" "hive-controller" "tls" "leafValidityDays" ]
|
|
''
|
|
No hive CA is generated any more: the gateway leaf is issued by the
|
|
secret store's pki mount, whose per-hive role sets its lifetime
|
|
(services.hyperhive.deploy.bao.servicesPkiLeafTtlHours). Remove this
|
|
definition. See docs/swarm/ca.md.
|
|
''
|
|
)
|
|
|
|
# The WireGuard mesh, whole. Unlike every rename above this one covers a
|
|
# namespace rather than a toggle: nothing under it is a fact another hive
|
|
# reads. A peer needs this host's `wireguardEndpoint` — the roster entry
|
|
# in ./swarm.nix, which stays — and nothing about the interface this host
|
|
# brings up. `listenPort` follows for the same reason and is easy to read
|
|
# the other way: it is what this host *binds*, while the port a peer
|
|
# *dials* is the one inside `wireguardEndpoint`.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "wireguard" "enable" ]
|
|
[ "services" "hyperhive" "deploy" "wireguard" "enable" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "wireguard" "privateKeyFile" ]
|
|
[ "services" "hyperhive" "deploy" "wireguard" "privateKeyFile" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "wireguard" "address" ]
|
|
[ "services" "hyperhive" "deploy" "wireguard" "address" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "wireguard" "listenPort" ]
|
|
[ "services" "hyperhive" "deploy" "wireguard" "listenPort" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "wireguard" "persistentKeepalive" ]
|
|
[ "services" "hyperhive" "deploy" "wireguard" "persistentKeepalive" ]
|
|
)
|
|
|
|
# Which build a service runs is a decision of the host that runs it, so
|
|
# every `*.package` follows its `enable` across. Left in separate
|
|
# namespaces they split one client's two halves, as `gui.enable` and
|
|
# `gui.package` would.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "matrix" "package" ]
|
|
[ "services" "hyperhive" "deploy" "matrix" "package" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "matrix" "gui" "package" ]
|
|
[ "services" "hyperhive" "deploy" "matrix" "gui" "package" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "grafana" "package" ]
|
|
[ "services" "hyperhive" "deploy" "grafana" "package" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "victorialogs" "package" ]
|
|
[ "services" "hyperhive" "deploy" "victorialogs" "package" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "victoriametrics" "package" ]
|
|
[ "services" "hyperhive" "deploy" "victoriametrics" "package" ]
|
|
)
|
|
# With this one `services.hyperhive.swarm.ui` holds nothing at all: its
|
|
# `enable` is an ignored switch (declared below) and its `package` is renamed here.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "ui" "package" ]
|
|
[ "services" "hyperhive" "deploy" "swarm-ui" "package" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "nats" "authPackage" ]
|
|
[ "services" "hyperhive" "deploy" "nats" "authPackage" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "authelia" "package" ]
|
|
[ "services" "hyperhive" "deploy" "authelia" "package" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "authelia" "bridgePackage" ]
|
|
[ "services" "hyperhive" "deploy" "authelia" "bridgePackage" ]
|
|
)
|
|
# ⚠️ `swarm-controller`, not `hive-controller` — see the note in
|
|
# ./swarm-controller.nix. Both namespaces exist, so the wrong target here
|
|
# lands on a live option in hive-c0re's tree instead of failing.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "controller" "package" ]
|
|
[ "services" "hyperhive" "deploy" "swarm-controller" "package" ]
|
|
)
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "controller" "swarmctlPackage" ]
|
|
[ "services" "hyperhive" "deploy" "swarm-controller" "swarmctlPackage" ]
|
|
)
|
|
# ⚠️ `deploy.forgejo`, not `deploy.forge` — the deploy-side name differs
|
|
# from the swarm-side one here, as it does for the controller and the UI.
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarm" "forge" "package" ]
|
|
[ "services" "hyperhive" "deploy" "forgejo" "package" ]
|
|
)
|
|
];
|
|
|
|
# ⚠️ Only `deploy.forgejo.enable` is declared here. The rest of
|
|
# `deploy.forgejo` is in ./hive-forge/default.nix: the knobs live with the
|
|
# module that reads them; this file stays the registry of toggles.
|
|
options.services.hyperhive.swarm.ui.enable = swarmUiSwitchIgnored;
|
|
|
|
config.warnings =
|
|
swarmUiSwitchWarning "deploy.swarm-ui.enable" config.services.hyperhive.deploy.swarm-ui.enable
|
|
++ swarmUiSwitchWarning "swarm.ui.enable" config.services.hyperhive.swarm.ui.enable;
|
|
|
|
options.services.hyperhive.deploy = {
|
|
swarm-ui.enable = swarmUiSwitchIgnored;
|
|
forgejo.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
example = true;
|
|
description = ''
|
|
Run the swarm's forge in a `hive-forge` container on this host. A
|
|
swarm has one forge, so one host turns this on. It is the
|
|
canonical store for the meta flake and every agent's config repo,
|
|
so the swarm needs it, but *this* host running it is a decision
|
|
like any other shared service's.
|
|
|
|
With it off, this hive is a *client*: it reaches the swarm's
|
|
forge at {option}`services.hyperhive.swarm.forge.domain`, which
|
|
the operator's DNS must resolve to the forge's host. No container
|
|
is created, and an existing one's state stays on disk under
|
|
`/var/lib/nixos-containers/hive-forge/`.
|
|
|
|
{option}`services.hyperhive.deploy.allSwarmServices` turns it on,
|
|
and `singleHostSwarm` through that.
|
|
'';
|
|
};
|
|
|
|
grafana.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Run the swarm's metrics UI on this host.
|
|
|
|
Off by default and not derived from
|
|
{option}`services.hyperhive.deploy.hive-controller.enable`: a swarm
|
|
has one Grafana, so running it is a decision about this host rather
|
|
than about whether it runs a hive.
|
|
'';
|
|
};
|
|
|
|
victoriametrics.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Run the swarm's metrics store on this host.
|
|
|
|
Paired with
|
|
{option}`services.hyperhive.deploy.grafana.enable`: 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
|
|
that switch. Set either directly to run exactly one.
|
|
'';
|
|
};
|
|
|
|
victorialogs.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Run the swarm's log store on this host.
|
|
|
|
A hive that is not the service host is a *client* of this store,
|
|
not a second one.
|
|
'';
|
|
};
|
|
|
|
bao.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
example = true;
|
|
description = ''
|
|
Run the swarm's secret store in a `swarm-bao` container on this
|
|
host. A swarm has one store and it has to exist somewhere.
|
|
|
|
*Where* it runs is a separate question from *that* it runs: set
|
|
this directly to put the store on a host of its own, and clients
|
|
still reach it by name at
|
|
{option}`services.hyperhive.swarm.bao.domain` rather than at a
|
|
local address.
|
|
|
|
With it off, this hive is a *client*: it still reads its own
|
|
secrets from whoever runs the store, authenticating with its own
|
|
client certificate. Every hive needs the client half; only one
|
|
runs the server half, which is why the two live in different
|
|
namespaces.
|
|
'';
|
|
};
|
|
|
|
authelia.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
example = true;
|
|
description = ''
|
|
Run the swarm's authelia in a `swarm-authelia` container on this
|
|
host. A swarm has one SSO provider, and this says it lives here.
|
|
|
|
With it off, this hive is a *client*:
|
|
{option}`services.hyperhive.swarm.authelia.url` still points at
|
|
whoever runs it, and no container is created. That asymmetry is
|
|
why the two live in different namespaces — every hive needs the
|
|
client half, only one runs the server half.
|
|
'';
|
|
};
|
|
|
|
swarm-otel.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Run the **swarm's** telemetry collector on this host.
|
|
|
|
A swarm has one of these, and it belongs wherever the shared
|
|
services live rather than on every hive.
|
|
|
|
Named `swarm-otel` rather than `otel` because there are two
|
|
collectors and the tier is the whole distinction:
|
|
{option}`services.hyperhive.otel.enable` is the **hive-tier** one,
|
|
which every hive runs. A bare `deploy.otel` would not say which
|
|
it meant. A hive that does not run the swarm collector still runs
|
|
its own, and reaches this one by name at
|
|
{option}`services.hyperhive.swarm.otel.domain`.
|
|
'';
|
|
};
|
|
|
|
matrix.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Run the swarm's matrix homeserver — matrix-tuwunel, in a
|
|
`hive-matrix` container — on this host.
|
|
|
|
Set it directly to put the homeserver somewhere other than the
|
|
host holding the rest of the swarm's services.
|
|
|
|
Client-side settings stay in
|
|
{option}`services.hyperhive.swarm.matrix.*`, which every hive
|
|
agrees on; this is only the decision to run it here.
|
|
'';
|
|
};
|
|
|
|
nats.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Run the swarm's message queue in a `swarm-nats` container on this
|
|
host. A swarm has one queue, so at most one host turns this on —
|
|
but *which* host is its own decision, not necessarily the one
|
|
running the swarm's other shared services.
|
|
|
|
Off by default, and off means *absent*: no container is created
|
|
and nothing else in the evaluated config changes.
|
|
'';
|
|
};
|
|
|
|
ci-runner.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
example = true;
|
|
description = ''
|
|
Run the swarm's Forgejo Actions runner in a `swarm-ci-runner`
|
|
container on this host. It reaches the forge at
|
|
{option}`services.hyperhive.swarm.forge.domain` and registers with
|
|
the token swarm-controller publishes to the secret store, so it
|
|
needs neither the forge nor a hive on this host.
|
|
|
|
Not derived from
|
|
{option}`services.hyperhive.deploy.allSwarmServices`: a runner
|
|
executes pull-request code, so running one is a decision of its own.
|
|
'';
|
|
};
|
|
|
|
review-classifier.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
example = true;
|
|
description = ''
|
|
Run the review classifier in a `swarm-review-classifier` container on
|
|
this host. It answers the swarm UI's review try-outs with `claude` on
|
|
the Anthropic API key the operator writes to the secret store at
|
|
`secret/swarm/services/review-classifier/anthropic-api-key`, field
|
|
`api_key`.
|
|
|
|
On by default where
|
|
{option}`services.hyperhive.deploy.allSwarmServices` is set and this
|
|
host has the classifier's store identity (the pair
|
|
{option}`services.hyperhive.deploy.bao.reviewClassifierClientCertFile`
|
|
and `reviewClassifierClientKeyFile`, minted on the store's host). The
|
|
key is never written for you: until the operator writes it the service
|
|
runs and every run fails with "no API key…".
|
|
'';
|
|
};
|
|
|
|
builder.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
example = true;
|
|
description = ''
|
|
Run the swarm builder in a `swarm-builder` container on this host. It
|
|
builds each agent config PR's head on this host's agent base, through
|
|
this host's nix daemon, and swarm-controller writes the result as a
|
|
`swarm-builder` commit status on the PR.
|
|
|
|
Not derived from
|
|
{option}`services.hyperhive.deploy.allSwarmServices`: the builder
|
|
evaluates and builds unreviewed config PRs on this host's nix daemon,
|
|
so running one is a decision of its own, as for the CI runner. It needs
|
|
the builder's store identity
|
|
({option}`services.hyperhive.deploy.bao.builderClientCertFile` and
|
|
`builderClientKeyFile`), which the store's host mints.
|
|
'';
|
|
};
|
|
|
|
hive-controller.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
example = true;
|
|
description = ''
|
|
Run a hive on this host: the `hive-c0re` coordinator that owns every
|
|
agent container here, its `hive-priv` helper, and the bridge,
|
|
resolver and gateway the agents hang off.
|
|
|
|
Every hive turns this on. A host that only runs the swarm's shared
|
|
services ({option}`services.hyperhive.deploy.allSwarmServices`)
|
|
leaves it off.
|
|
'';
|
|
};
|
|
|
|
swarm-controller.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Run the swarm-controller daemon on this host.
|
|
|
|
Off by default and deliberately not derived from
|
|
{option}`services.hyperhive.deploy.hive-controller.enable`: a swarm
|
|
has one controller, so running it is a decision about this host
|
|
rather than about whether it runs a hive.
|
|
|
|
Also serves the swarm UI from this host. The UI is a view onto the
|
|
controller's state and reaches it over that daemon's unix socket,
|
|
so the host that runs the controller is the only host that can
|
|
serve it.
|
|
'';
|
|
};
|
|
};
|
|
}
|