hyperhive — deploy options
services.hyperhive.deploy.allSwarmServices
Host the swarm’s shared services on this hive. The services that exist once per swarm rather than once per hive — the forge, 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.
Every toggle it asserts is a services.hyperhive.deploy.*
one, because “does THIS host run it” is a per-host decision — which
is the same reason this option is a deploy.* one itself. See
./deploy.nix.
services.hyperhive.deploy.singleHostSwarm 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.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.authelia.enable
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:
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.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.authelia.package
authelia package to run in the container. Defaults to nixpkgs’s; override to pin a specific upstream.
Type: package
Default:
pkgs.authelia
Declared by:
services.hyperhive.deploy.authelia.bridgePackage
swarm-authelia-bridge package — the only process allowed to
write usersFile. Wired by default from this flake’s own
package set (see flake.nix); override to run a different
build.
Type: package
Default:
hyperhive.packages.${system}.swarm-authelia-bridge
Declared by:
services.hyperhive.deploy.authelia.hostClientSecretDir
Where the minted client secrets sit as seen from the host —
<id>.secret holds a plaintext, <id>.digest the hash authelia
itself reads.
Published for the same reason as hostUsersFile: the plaintext’s
other reader lives in a different container, and containers
that share this host’s network namespace still have separate
filesystem roots. The host is the only place both trees are
addressable, so the host is where a delivery step has to run.
⚠️ Nothing here exists until authelia’s first boot has run.
A consumer must wait for it — it cannot be a bindMounts source,
because nixos-container refuses to start when a bind source is
missing, and that turns a fresh hive into a boot-order deadlock.
Type: string (read only)
Default:
"/var/lib/nixos-containers/swarm-authelia/var/lib/authelia-swarm/oidc-clients"
Declared by:
services.hyperhive.deploy.authelia.hostUsersFile
usersFile as seen from the host — the container’s root
prefixed onto the path authelia sees.
Published for callers that only ever need to read the file
(e.g. an operator diagnosing a bad entry). swarm-authelia-bridge
itself never uses this path — it runs inside the container, as
the file’s own owner, and writes the in-container path directly.
Type: string (read only)
Default:
"/var/lib/nixos-containers/swarm-authelia/var/lib/authelia-swarm/users.yml"
Declared by:
services.hyperhive.deploy.authelia.usersFile
Path (inside the container) of authelia’s file users database.
Written by swarm-authelia-bridge, not by hand: agents come and
go continuously, so the subject set is dynamic and belongs to a
program. swarm-controller cannot write this file itself — a
different uid owns it — so the bridge is the only writer,
running inside this same container as this file’s actual owner.
When the user set is empty this module writes a single
disabled placeholder subject, swarm.placeholder, so authelia
starts and serves its login page; nobody can log in until
swarmctl user add creates the first account.
Type: string
Default:
"/var/lib/authelia-swarm/users.yml"
Declared by:
services.hyperhive.deploy.bao.enable
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
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.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.bao.package
OpenBao package to run.
⚠️ An assertion below refuses 2.7.0 or newer, which drops the built-in PKCS11 seal.
Type: package
Default:
pkgs.openbao
Declared by:
services.hyperhive.deploy.bao.agentPkiMountPath
Mount path of the PKI engine agent client certificates are issued from. Its root is generated inside the store and its key never leaves it.
An option rather than a literal because the store host sets the mount up while swarm-controller, possibly on another host, issues through it: both have to spell it identically.
Type: string
Default:
"pki-agents"
Declared by:
services.hyperhive.deploy.bao.agentPkiRoleName
Role on services.hyperhive.deploy.bao.agentPkiMountPath
agent client certificates are issued through. It issues client
certificates named hive-agent-* and nothing else, and swarm-controller
may call its issue endpoint and no other path on the mount.
Type: string
Default:
"swarm-agent"
Declared by:
services.hyperhive.deploy.bao.bootstrapTokenFile
Token used once per swarm to create the store’s cert-auth mount and
the bao-granter policy and role, after which every granting unit
logs in as the granter with a certificate instead.
Cert auth answers a role, so no client can authenticate until some role exists — and creating the granter’s is what this token is for. It has to come from outside that cycle, which is why an operator places it rather than the deployment minting it.
Produce it from the root token bao operator init printed, under the
bao-bootstrap policy shipped at
/etc/hyperhive/bao-bootstrap-policy.hcl, then delete it once
swarm-bao-granter-role has run —
docs/getting-started/setup.md has the commands. Setting this is
what renders swarm-bao-granter-role; while it is null, a store whose
granter is not set up has no way to set it up.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-bootstrap/grant.token"
Declared by:
services.hyperhive.deploy.bao.builderClientCertFile
Certificate the swarm builder presents to the store. Its subject must
be services.hyperhive.deploy.bao.builderCommonName.
./glue-bao-tls.nix points it at the leaf it mints on the store’s host. On a builder host without the store, it is a file the operator copies from the store’s host. A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/builder.pem"
Declared by:
services.hyperhive.deploy.bao.builderClientKeyFile
Private key for
services.hyperhive.deploy.bao.builderClientCertFile.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/builder-key.pem"
Declared by:
services.hyperhive.deploy.bao.builderCommonName
Subject the store’s swarm-builder cert-auth role accepts: the
identity the swarm builder presents from inside its container. Its
grant is two paths, read only: swarm/services/builder/forge/token
and its own queue client secret.
⚠️ Reserved as a hive name by ./swarm.nix, like its siblings.
Type: string
Default:
"swarm-builder"
Declared by:
services.hyperhive.deploy.bao.ciRunnerClientCertFile
Certificate the unit that fetches the CI runner’s registration token
presents to the store. Its subject must be
services.hyperhive.deploy.bao.ciRunnerCommonName.
./glue-bao-tls.nix points it at the leaf it mints on the store’s host. On a runner host without the store, it is a file the operator copies from the store’s host. A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/ci-runner.pem"
Declared by:
services.hyperhive.deploy.bao.ciRunnerClientKeyFile
Private key for
services.hyperhive.deploy.bao.ciRunnerClientCertFile.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/ci-runner-key.pem"
Declared by:
services.hyperhive.deploy.bao.ciRunnerCommonName
Subject the store’s swarm-ci-runner cert-auth role accepts: the
identity swarm-bao-ci-runner, the unit that fetches the forge’s
runner registration token for the CI runner, presents. Its grant is one
path, swarm/services/ci-runner/registration-token, and read only.
⚠️ Reserved as a hive name by ./swarm.nix, like its siblings.
Type: string
Default:
"swarm-ci-runner"
Declared by:
services.hyperhive.deploy.bao.clientCaFile
Authority the store validates hive client certificates against.
This module declares no default, and the store’s own pki root
can’t be this authority: a store that authenticated against a root
it issues could not come up before the thing it issues.
On a hive that runs the store, a glue module supplies the CA it
minted for exactly this, as a mkDefault. Point this at something
else — an operator’s own CA — and yours wins.
null leaves client-certificate verification off, which is only
appropriate where something else authenticates the connection.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/ca.pem"
Declared by:
services.hyperhive.deploy.bao.clientCertFile
Certificate a reader on this machine presents to the store.
The counterpart to services.hyperhive.deploy.bao.clientCaFile,
which is the store’s side of the same handshake.
On a hive that runs the store, a glue module supplies the leaf it minted,
as a mkDefault. Everywhere else this is the credential an operator
places by hand — the one secret that cannot come out of the store,
because it is what opens it.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao/client.pem"
Declared by:
services.hyperhive.deploy.bao.clientKeyFile
Private key for services.hyperhive.deploy.bao.clientCertFile.
Both or neither — a certificate with no key authenticates nothing.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao/client-key.pem"
Declared by:
services.hyperhive.deploy.bao.controllerCommonName
Subject the store’s swarm-controller cert-auth role accepts. An
interface, not a label: cert auth matches on the CN, so whatever mints
the controller’s leaf has to spell it the same way.
Lives here because it is a property of the role, which this module writes — not a credential belonging to the controller. Nothing outside the store needs it except whatever issues that leaf.
⚠️ Reserved as a hive name. A hive’s own leaf carries its name as the
CN, so a hive named after this subject would satisfy the role —
./swarm.nix feeds this value into the guard on
services.hyperhive.swarm.hives to make that unrepresentable.
Type: string
Default:
"swarm-controller"
Example:
"swarm-controller.svc"
Declared by:
services.hyperhive.deploy.bao.extraListenAddresses
Addresses the store listens on in addition to loopback, each on
services.hyperhive.swarm.bao.port.
Loopback is unconditional and not listed here: the host running the store is always one of its readers. Every other address depends on which network the reading hives share with this one, and that is a deployment fact no other module’s config can be read to infer — a swarm meshed over wireguard names its mesh address, one on a trusted LAN names that interface, and an all-local swarm names nothing at all.
Addresses only, no port: a store reachable on two ports is a misconfiguration rather than a topology.
Type: list of string
Default:
[ ]
Example:
[
"10.100.0.1"
]
Declared by:
services.hyperhive.deploy.bao.forgePublisherClientCertFile
Certificate the forge’s host presents to the store, both to publish the
swarm-controller’s forge token and to fetch the forge’s OIDC client
secret. Its subject must be
services.hyperhive.deploy.bao.forgePublisherCommonName.
./glue-bao-tls.nix points it at the leaf it mints on the store’s host. On a forge host without the store, it is a file the operator copies from the store’s host. A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/forge-publisher.pem"
Declared by:
services.hyperhive.deploy.bao.forgePublisherClientKeyFile
Private key for
services.hyperhive.deploy.bao.forgePublisherClientCertFile.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/forge-publisher-key.pem"
Declared by:
services.hyperhive.deploy.bao.forgePublisherCommonName
Subject the store’s swarm-forge-publisher cert-auth role accepts: the
forge host’s one store identity, presented by swarm-bao-forge-publisher,
which publishes the swarm-controller’s forge token, and by
swarm-bao-forge-oidc, which fetches the forge’s OIDC client secret.
Its grant is two paths: swarm/controller/swarm-controller/forge/token,
write only, and swarm/services/<forge client id>/oidc/client, read
only.
⚠️ Reserved as a hive name by ./swarm.nix, like its siblings.
Type: string
Default:
"swarm-forge-publisher"
Declared by:
services.hyperhive.deploy.bao.forwarderOidcClientCertFile
Certificate the unit that fetches the store’s own forwarder’s OIDC
client secret presents to the store. Its subject must be
services.hyperhive.deploy.bao.forwarderOidcCommonName.
⚠️ Not the hive’s own leaf, for the reason
services.hyperhive.deploy.bao.queueAgentClientCertFile gives.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/forwarder-oidc.pem"
Declared by:
services.hyperhive.deploy.bao.forwarderOidcClientKeyFile
Private key for
services.hyperhive.deploy.bao.forwarderOidcClientCertFile.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/forwarder-oidc-key.pem"
Declared by:
services.hyperhive.deploy.bao.forwarderOidcCommonName
Subject the store’s swarm-forwarder-oidc cert-auth role accepts — the
identity swarm-bao-forwarder-oidc, the unit that fetches the store’s
own forwarder’s OIDC client secret, presents. Its grant is one path,
swarm/services/<forwarder client id>/oidc/client, and read only.
Its own identity rather than reuse of
services.hyperhive.deploy.bao.otelOidcCommonName: the two
read different clients’ secrets, and the store’s forwarder is not
entitled to the swarm collector’s.
Type: string
Default:
"swarm-bao-forwarder-oidc"
Example:
"swarm-bao-forwarder-oidc.svc"
Declared by:
services.hyperhive.deploy.bao.grafanaOidcClientCertFile
Certificate the unit that fetches Grafana’s OIDC client secret presents
to the store. Its subject must be
services.hyperhive.deploy.bao.grafanaOidcCommonName.
⚠️ Not the hive’s own leaf, for the reason
services.hyperhive.deploy.bao.queueAgentClientCertFile gives.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/grafana-oidc.pem"
Declared by:
services.hyperhive.deploy.bao.grafanaOidcClientKeyFile
Private key for
services.hyperhive.deploy.bao.grafanaOidcClientCertFile.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/grafana-oidc-key.pem"
Declared by:
services.hyperhive.deploy.bao.grafanaOidcCommonName
Subject the store’s swarm-grafana-oidc cert-auth role accepts — the
identity the unit that fetches Grafana’s OIDC client secret presents.
Its grant is one path,
swarm/services/<grafana client id>/oidc/client, and read only. Not
per hive, unlike the two prefixes above: an OIDC client is registered
once per swarm, so the path names the service and never a hive.
⚠️ Same collision as its siblings, and the same answer: ./swarm.nix
feeds this value into the guard on
services.hyperhive.swarm.hives.
Type: string
Default:
"swarm-bao-grafana-oidc"
Example:
"swarm-bao-grafana-oidc.svc"
Declared by:
services.hyperhive.deploy.bao.granterClientCertFile
Certificate the store’s granting units present to the store. Its
subject must be
services.hyperhive.deploy.bao.granterCommonName.
Null, or a null
services.hyperhive.deploy.bao.clientCaFile, means this
deployment writes those grants some other way: no granting unit
renders.
⚠️ Unlike every other leaf the store’s host mints, this one is never copied to another host; its only reader is that host.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/granter.pem"
Declared by:
services.hyperhive.deploy.bao.granterClientKeyFile
Private key for
services.hyperhive.deploy.bao.granterClientCertFile.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/granter-key.pem"
Declared by:
services.hyperhive.deploy.bao.granterCommonName
Subject the store’s bao-granter cert-auth role accepts: the identity
every swarm-bao-*-policy unit on the store’s host logs in as to write
the swarm-* policies, cert-auth roles and pki roles.
⚠️ Root-equivalent: it may write a swarm-* policy with any content.
Reserved as a hive name by ./swarm.nix, like its siblings.
Type: string
Default:
"bao-granter"
Declared by:
services.hyperhive.deploy.bao.hiveLeafCommonNamePrefix
Prefix of the subject the store’s per-hive gateway-leaf roles accept.
The role for hive h accepts <prefix>-h and may only issue from
<servicesPkiMountPath>/issue/<hiveLeafPkiRolePrefix>-h, which issues
for h’s domain and *. that domain and nothing else.
Per hive for the reason
services.hyperhive.deploy.bao.queueAgentCommonNamePrefix is:
one subject for every hive could ask for any hive’s certificate.
⚠️ Reserved as a hive name by ./swarm.nix, per hive, like its siblings.
Type: string
Default:
"swarm-bao-hive-leaf"
Example:
"swarm-bao-hive-leaf.svc"
Declared by:
services.hyperhive.deploy.bao.hiveLeafPkiRolePrefix
Prefix of the per-hive roles on
services.hyperhive.deploy.bao.servicesPkiMountPath that each
hive’s gateway leaf is issued through: <prefix>-<hive>. The same name
is that hive’s policy and cert-auth role. Must start with swarm-.
Type: string
Default:
"swarm-hive-leaf"
Declared by:
services.hyperhive.deploy.bao.logsAuthCommonName
Subject the store’s swarm-logs-auth cert-auth role accepts: the
identity the log store’s agent auth responder presents to read agent
queue credentials, swarm/agents/<agent>/queue and nothing else under
an agent.
⚠️ Reserved as a hive name by ./swarm.nix, like its siblings.
Type: string
Default:
"swarm-logs-auth"
Declared by:
services.hyperhive.deploy.bao.matrixCtlCommonName
Subject the store’s matrix-ctl cert-auth role accepts — the
identity the matrix container’s swarm-matrix-appservice-publish
unit presents when it publishes the swarm appservice’s token.
A third identity rather than reuse of either sibling above, and the narrowest of the three: its grant is one path, that credential itself. The point of the whole arrangement is that the process holding the appservice token is not the hive, so handing it the hive’s own leaf — which reads every agent credential in the swarm and this hive’s own secrets — would give the separation away in one line.
⚠️ Same collision as its siblings, and the same answer: ./swarm.nix
feeds this value into the guard on
services.hyperhive.swarm.hives, so a hive named after it
fails evaluation rather than silently receiving matrix-ctl’s grant.
Type: string
Default:
"swarm-matrix-ctl"
Example:
"swarm-matrix-ctl.svc"
Declared by:
services.hyperhive.deploy.bao.metricsPort
Loopback port the store serves its Prometheus metrics on, scraped by a collector on this same host.
Here and not beside services.hyperhive.swarm.bao.port
because no client of the store ever needs it: reaching this port
means being the local collector, which is a property of the host
running the store.
⚠️ Cannot be services.hyperhive.swarm.bao.port + 1 —
openbao derives every listener’s cluster address as its own port plus
one, so the API listener already holds that number. The default sits
one above it, and its own derived cluster address one above that.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
8202
Declared by:
services.hyperhive.deploy.bao.natsAuthCommonName
Subject the store’s swarm-nats-auth cert-auth role accepts: the
identity the queue’s auth-callout responder presents to read agent
queue credentials, swarm/agents/<agent>/queue and nothing else under
an agent.
Its own principal rather than
services.hyperhive.deploy.bao.natsCommonName: that one
issues the queue’s TLS leaf from a host unit, this one reads secrets
from inside the queue’s container.
⚠️ Reserved as a hive name by ./swarm.nix, like its siblings.
Type: string
Default:
"swarm-nats-auth"
Declared by:
services.hyperhive.deploy.bao.natsCommonName
Subject the store’s swarm-nats cert-auth role accepts: the identity
the queue’s host presents to ask for the queue’s TLS leaf.
Its own principal rather than
services.hyperhive.deploy.bao.servicesIssuerCommonName,
whose role issues for every name in
services.hyperhive.swarm.serviceDomains. This one may issue
from services.hyperhive.deploy.bao.natsPkiRoleName alone,
and that role only for services.hyperhive.swarm.nats.domain.
⚠️ Reserved as a hive name by ./swarm.nix, like its siblings.
Type: string
Default:
"swarm-nats"
Declared by:
services.hyperhive.deploy.bao.natsPkiRoleName
Role on services.hyperhive.deploy.bao.servicesPkiMountPath
the queue’s TLS leaf is issued through. It allows exactly
services.hyperhive.swarm.nats.domain: no subdomains, IPs or
localhost.
Type: string
Default:
"swarm-nats"
Declared by:
services.hyperhive.deploy.bao.otelOidcClientCertFile
Certificate the unit that fetches the collector’s OIDC client secret
presents to the store. Its subject must be
services.hyperhive.deploy.bao.otelOidcCommonName.
⚠️ Not the hive’s own leaf, for the reason
services.hyperhive.deploy.bao.queueAgentClientCertFile gives.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/otel-oidc.pem"
Declared by:
services.hyperhive.deploy.bao.otelOidcClientKeyFile
Private key for
services.hyperhive.deploy.bao.otelOidcClientCertFile.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/otel-oidc-key.pem"
Declared by:
services.hyperhive.deploy.bao.otelOidcCommonName
Subject the store’s swarm-otel-oidc cert-auth role accepts — the
identity the unit that fetches the collector’s OIDC client secret
presents. Its grant is one path,
swarm/services/<collector client id>/oidc/client, and read only.
Its own identity rather than reuse of
services.hyperhive.deploy.bao.grafanaOidcCommonName: the two
read different services’ client secrets, and a collector is not
entitled to Grafana’s.
Type: string
Default:
"swarm-bao-otel-oidc"
Example:
"swarm-bao-otel-oidc.svc"
Declared by:
services.hyperhive.deploy.bao.queueAgentClientCertFile
Certificate the unit that fetches this hive’s queue client credential
presents to the store. Its subject must be
<queueAgentCommonNamePrefix>-<this hive's name>; cert auth matches on
the CN and the role accepts nothing else.
⚠️ Not services.hyperhive.deploy.bao.clientCertFile.
Pointing this at the hive’s own leaf would evaluate, deploy and log in —
and hand a unit that reads one credential a certificate that reads every
agent credential in the swarm and this hive’s own secrets.
No default here: ./glue-bao-tls.nix points it at the leaf it mints, wherever this host mints its own PKI. A deployment that reads a store on another host names it by hand, alongside the leaf itself.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/queue-agent.pem"
Declared by:
services.hyperhive.deploy.bao.queueAgentClientKeyFile
Private key for
services.hyperhive.deploy.bao.queueAgentClientCertFile.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/queue-agent-key.pem"
Declared by:
services.hyperhive.deploy.bao.queueAgentCommonNamePrefix
Prefix of the subject the store’s per-hive queue-credential roles
accept. The role for hive h accepts <prefix>-h and grants read on
exactly swarm/hives/h/queue/agent — the client credential that hive’s
agent containers authenticate to the swarm queue with.
A prefix rather than one subject because every hive runs its own
reader and the path it reads carries that hive’s name. One subject for
all of them would need a hives/* grant, which would let one hive read
another hive’s queue credential.
⚠️ Reserved as a hive name by ./swarm.nix, per hive, for the reason its
fixed-subject siblings are: cert auth trusts the CA and
allowed_common_names is the whole narrowing, so a hive whose own leaf
carried one of these spellings would receive that grant.
Type: string
Default:
"swarm-bao-queue-agent"
Example:
"swarm-bao-queue-agent.svc"
Declared by:
services.hyperhive.deploy.bao.reviewClassifierClientCertFile
Certificate the review classifier presents to the store. Its subject
must be
services.hyperhive.deploy.bao.reviewClassifierCommonName.
./glue-bao-tls.nix points it at the leaf it mints on the store’s host. On a classifier host without the store, it is a file the operator copies from the store’s host. A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/review-classifier.pem"
Declared by:
services.hyperhive.deploy.bao.reviewClassifierClientKeyFile
Private key for
services.hyperhive.deploy.bao.reviewClassifierClientCertFile.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/review-classifier-key.pem"
Declared by:
services.hyperhive.deploy.bao.reviewClassifierCommonName
Subject the store’s swarm-review-classifier cert-auth role accepts:
the identity the review classifier presents from inside its
container. Its grant is three paths, read only:
swarm/services/review-classifier/anthropic-api-key,
swarm/services/review-classifier/acp-provider and its own queue
client secret.
⚠️ Reserved as a hive name by ./swarm.nix, like its siblings.
Type: string
Default:
"swarm-review-classifier"
Declared by:
services.hyperhive.deploy.bao.seal
How the store’s root key is sealed.
pkcs11 is the default and binds the key to the host’s TPM: the store
unseals itself at boot, and an attacker with the disk does not get the
secrets. shamir is openbao’s own default — unseal keys held by
whoever ran bao operator init, entered by hand after every restart —
and is the honest choice for a host with no TPM.
⚠️ This is a declaration, and nothing at evaluation time can check
it: nix runs on the build machine and cannot see the target’s TPM.
Saying pkcs11 on a host without one fails when the store’s container
starts and its provisioning unit cannot create the token — later than
activation, and on the container’s journal. That is deliberate — a
store that comes up sealed by software while the config says hardware
is weaker than it reads, and silently so.
Type: one of “pkcs11”, “shamir”
Default:
"pkcs11"
Example:
"shamir"
Declared by:
services.hyperhive.deploy.bao.secretPublisherCommonName
Subject the store’s secret-publisher cert-auth role accepts — the identity that copies authelia’s minted OIDC client secrets into the store so a hive that does not host authelia can read its own.
A second identity rather than reuse of
services.hyperhive.deploy.bao.controllerCommonName: the
controller’s grant includes rewriting every hive’s policy and login
role, which is not something a unit whose whole job is copying one file
should be able to do. This one’s grant is create/update under the
hive prefix and nothing else.
⚠️ Same collision as its sibling above, and the same answer: ./swarm.nix
feeds this value into the guard on
services.hyperhive.swarm.hives, so a hive named after it fails
evaluation rather than silently receiving the publisher’s grants.
Type: string
Default:
"swarm-secret-publisher"
Example:
"swarm-secret-publisher.svc"
Declared by:
services.hyperhive.deploy.bao.serverCaFile
Authority a reader on this machine validates the store’s certificate against.
Not services.hyperhive.deploy.bao.clientCaFile with the words
rearranged: that one is the store choosing which readers to trust, this
one is a reader choosing which store to trust. A deployment that
self-signs both ends points them at the same file and reads that as
confirmation they are interchangeable — they are not, and they diverge
the moment either end gets a real CA.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao/ca.pem"
Declared by:
services.hyperhive.deploy.bao.serverCertFile
Certificate the store serves, covering
services.hyperhive.swarm.bao.domain.
This module declares no default and deliberately does not know
what could provide one — for the same reason
services.hyperhive.deploy.bao.clientCaFile doesn’t: the
store never reaches for an authority.
On a hive that runs the store, a glue module supplies a path as a
mkDefault, so naming your own here wins over it.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao/server.pem"
Declared by:
services.hyperhive.deploy.bao.serverKeyFile
Private key for services.hyperhive.deploy.bao.serverCertFile.
Both or neither — a certificate with no key is a listener that cannot
start.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao/server-key.pem"
Declared by:
services.hyperhive.deploy.bao.servicesIssuerClientCertFile
Certificate swarm-services-cert logs in to the store with to ask for
the swarm-services leaf the gateway serves. Its subject must be
services.hyperhive.deploy.bao.servicesIssuerCommonName.
⚠️ Neither the reader’s
services.hyperhive.deploy.bao.clientCertFile nor a hive’s own
identity: this one’s policy permits update on
pki/issue/swarm-services and nothing else, and it is the same on
every gateway host, whether or not a hive runs there.
Required on every self-signed gateway host that fronts a swarm-service
name (services.hyperhive.swarm.localServiceDomains not
empty). Unset there, the host evaluates and swarm-services-cert
fails, naming both options. A host fronting none only fetches the
store’s root, presenting
services.hyperhive.deploy.hive-controller.tls.baoHiveIdentityCertFile,
and needs no services-issuer pair.
./glue-bao-tls.nix points it at the leaf it mints on the store’s host. On any other gateway host that needs it, it is a file the operator copies from the store’s host. A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/services-issuer.pem"
Declared by:
services.hyperhive.deploy.bao.servicesIssuerClientKeyFile
Private key for
services.hyperhive.deploy.bao.servicesIssuerClientCertFile.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/services-issuer-key.pem"
Declared by:
services.hyperhive.deploy.bao.servicesIssuerCommonName
Subject the store’s services-issuer cert-auth role accepts — the
identity a hive presents when it asks the pki mount for the
swarm-services certificate its gateway serves.
A fourth identity rather than reuse of any sibling above, and the
reasoning is theirs: this principal’s whole grant is one update on
pki/issue/swarm-services, while the controller’s includes rewriting
every hive’s policy and login role. Handing a certificate-renewal unit
the controller’s leaf would give that separation away in one line.
⚠️ Same collision as its siblings, and the same answer: ./swarm.nix
feeds this value into the guard on
services.hyperhive.swarm.hives, so a hive named after it
fails evaluation rather than silently receiving this grant.
Type: string
Default:
"swarm-services-issuer"
Example:
"swarm-services-issuer.svc"
Declared by:
services.hyperhive.deploy.bao.servicesPkiMountPath
Mount path of the PKI engine the swarm’s service certificates are issued from, and whose root is the anchor those certificates chain to.
An option rather than a literal because two files have to spell it
identically: this module enables the mount, generates its root and
writes the grant that points at <path>/issue/, while ./hive-tls.nix
calls that endpoint. A mount path only one of them knows is a grant
naming a location nobody issues from.
⚠️ NOT the store’s own client-auth PKI. That one is
./glue-bao-tls.nix’s self-signed CA on disk, and it stays outside the
store permanently — bao cannot issue the credential a host opens bao
with. Agent certificates come from
services.hyperhive.deploy.bao.agentPkiMountPath.
Type: string
Default:
"pki"
Declared by:
services.hyperhive.deploy.bao.servicesPkiRoleName
Role on services.hyperhive.deploy.bao.servicesPkiMountPath
that the swarm-services certificate is issued through, and the whole
narrowing of that mount.
A role rather than a name-constrained sub-CA: the engine enforces the
same “these names and no others” at issue time, from an
allowed_domains read off
services.hyperhive.swarm.serviceDomains, that an
intermediate would encode in x509 nameConstraints — so a second
authority in the chain would re-implement a check that has already
happened.
Type: string
Default:
"swarm-services"
Declared by:
services.hyperhive.deploy.bao.tpmGid
Numeric group id owning /dev/tpmrm0, so the store’s seal can open it.
⚠️ A number, and it has a default, because a name cannot do this
job. The store runs as a DynamicUser whose uid is allocated inside
its container, and NixOS allocates tss — and every other system
group — at activation, per machine. A group declared on the host and
a group of the same name declared in the container therefore get
different ids, and the device node carries the number. Pinning one
value is what makes the two sides agree.
The default sits above the range NixOS auto-assigns system groups from
(400–999) and above the normal-user range (1000–29999), and below the
range systemd allocates DynamicUser ids from (61184–65519), so it
collides with nothing those allocate. Override it if it collides with
something this module cannot see.
Only read when services.hyperhive.deploy.bao.seal is
pkcs11; a shamir store never touches the TPM.
Type: signed integer
Default:
31337
Example:
4242
Declared by:
services.hyperhive.deploy.bao.uiPort
Loopback port of the listener that serves the store’s browser UI.
It requires no client certificate, so only the nginx in the
store’s container proxies to it; see
services.hyperhive.deploy.bao.uiProxyPort.
⚠️ openbao also binds this port + 1 as the listener’s cluster address, so neither may coincide with another port the store or its container binds. An assertion checks this.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
8204
Declared by:
services.hyperhive.deploy.bao.uiProxyPort
Loopback port of the nginx inside the store’s container that fronts
services.hyperhive.deploy.bao.uiPort. The gateway’s
services.hyperhive.swarm.bao.ui.domain vhost proxies here.
This nginx forwards only /ui/ and /v1/, and refuses the
unseal, seal, step-down, rekey and generate-root endpoints.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
8206
Declared by:
services.hyperhive.deploy.builder.enable
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
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
(services.hyperhive.deploy.bao.builderClientCertFile and
builderClientKeyFile), which the store’s host mints.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.builder.package
The swarm builder daemon package.
Type: package
Default:
hyperhive.packages.${system}.swarm-builder
Declared by:
services.hyperhive.deploy.ci-runner.enable
Run the swarm’s Forgejo Actions runner in a swarm-ci-runner
container on this host. It reaches the forge at
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
services.hyperhive.deploy.allSwarmServices: a runner
executes pull-request code, so running one is a decision of its own.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.ci-runner.package
gitea-actions-runner package.
Type: package
Default:
pkgs.gitea-actions-runner
Declared by:
services.hyperhive.deploy.ci-runner.concurrency
Maximum number of workflow jobs the runner executes in parallel. Each job gets its own temporary working directory; parallel jobs share the host’s nix store and the container’s cargo registry cache. Higher values trade memory and CPU headroom for throughput.
Type: positive integer, meaning >0
Default:
1
Example:
4
Declared by:
services.hyperhive.deploy.ci-runner.jobTimeout
Per-job wall-clock timeout the runner enforces (act_runner’s
runner.timeout). A job that exceeds it is killed, so a hung build
does not hold a runner slot indefinitely. Accepts a Go duration
string (30m, 1h, 2h30m). Enforced by the runner process, so
it only fires while that process is healthy.
Type: string
Default:
"1h"
Example:
"3h"
Declared by:
services.hyperhive.deploy.ci-runner.labels
Runner labels in <name>:<scheme> format. The host scheme runs
commands directly in the container (no docker/podman). This repo’s
workflows target the default with runs-on: hive-ci.
Type: list of string
Default:
[
"hive-ci:host"
]
Example:
[
"hive-ci:host"
"nix:host"
]
Declared by:
services.hyperhive.deploy.ci-runner.name
Runner name as shown in the Forgejo admin panel.
Type: string
Default:
"swarm-ci-runner"
Declared by:
services.hyperhive.deploy.forgejo.enable
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 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/.
services.hyperhive.deploy.allSwarmServices turns it on,
and singleHostSwarm through that.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.forgejo.package
Forgejo package to run inside the container. Defaults to
pkgs.forgejo (the latest release line) rather than the
nixpkgs-module default of pkgs.forgejo-lts, because LTS
lags far behind on schema and the DB easily ends up “newer
than the binary” if the operator ever ran a non-LTS forgejo
against the same state dir. Override to pkgs.forgejo-lts
if you actively want the slower release train.
Type: package
Default:
pkgs.forgejo
Declared by:
services.hyperhive.deploy.forgejo.actionsFromSelf
Resolve a workflow’s uses: <org>/<action>@vN against this forge
instead of data.forgejo.org, and add actions/checkout and
actions/upload-artifact pull-mirrors to
services.hyperhive.deploy.forgejo.mirrors so those steps
have something to resolve to. A CI job’s actions then need no
external DNS; only the mirrors’ re-sync does.
Defaults to on when this host also runs the swarm-controller, which
seeds the mirrors (set by glue-forge-controller.nix), and off
otherwise. Setting it true on a host without
the controller leaves both actions unresolved: nothing seeds the
mirrors, and the warning about unseeded mirrors fires.
Any other action a workflow names has to be mirrored here too. Set to
false to resolve actions from data.forgejo.org and seed no mirror.
Type: boolean
Default:
false
Example:
false
Declared by:
services.hyperhive.deploy.forgejo.mirrors
General-purpose Forgejo pull-mirrors to auto-seed on the local
forge. Each entry is created as a real Forgejo pull-mirror (it
re-syncs from upstream out-of-band), not a one-off pushed clone —
so a host-resolver blip leaves a stale mirror, never a hard
failure on whatever reads it.
With services.hyperhive.deploy.forgejo.actionsFromSelf
enabled (the default on a host that runs the swarm-controller),
actions/checkout and actions/upload-artifact mirrors are appended
to this list.
Type: list of (submodule)
Default:
[ ]
Example:
[ { upstream = "https://github.com/actions/checkout"; dest = "actions/checkout"; } ]
Declared by:
services.hyperhive.deploy.forgejo.mirrors.*.dest
Local <owner>/<repo> the pull-mirror is created at. The
<owner> org is auto-created if missing. Keep mirror dests
in their own orgs (e.g. actions/*) — separate from the
hive-c0re-managed namespaces (config/shared/agents/core) so
the seed never collides with core’s own provisioning.
Type: string
Example:
"actions/checkout"
Declared by:
services.hyperhive.deploy.forgejo.mirrors.*.upstream
Upstream clone URL to mirror from.
Type: string
Example:
"https://github.com/actions/checkout"
Declared by:
services.hyperhive.deploy.forgejo.openFirewall
Open httpPort + sshPort in the host firewall. Off by
default (secure-by-default): agent containers reach the forge
at forge.<domain> via the gateway (not directly), and the
host reaches it on loopback — so the firewall opens only
matter for access from outside the host. Flip to true when
you want the operator’s browser or external git clients to
hit the forge directly.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.forgejo.sso.clientSecretFile
Path inside the forge container holding the client secret’s plaintext.
A path, never a value: an OIDC client secret has two holders in two containers (authelia keeps a hash, this forge needs the plaintext), and a literal written here would be rendered into the world-readable nix store.
Set to /var/lib/forgejo-oidc/<client id>.secret wherever the
forge runs. swarm-bao-forge-oidc writes the secret here from the
swarm secret store, whichever path this names.
Null is refused at eval: a forge that boots with SSO half-configured presents as a login button that always fails, which is harder to diagnose than an eval error.
Type: null or string
Default:
null
Example:
"/var/lib/forgejo-oidc/forgejo.secret"
Declared by:
services.hyperhive.deploy.grafana.enable
Run the swarm’s metrics UI on this host.
Off by default and not derived from
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.
Type: boolean
Default:
false
Declared by:
services.hyperhive.deploy.grafana.package
Grafana package to run.
Type: package
Default:
pkgs.grafana
Declared by:
services.hyperhive.deploy.grafana.datasourceUrl
Where the provisioned datasource points. Defaults to the metrics store’s swarm name, served by the gateway of whichever host runs the store, so Grafana and the store need not share a host. The store’s query routes on that vhost take no credential, so the datasource sends none.
Type: string
Default:
"https://${services.hyperhive.swarm.victoriametrics.domain}"
Declared by:
services.hyperhive.deploy.grafana.logsDatasourceUrl
Where the provisioned logs datasource points. Defaults to the log store on this host, which binds loopback, so this default reaches it only where Grafana and the store share a host.
Provisioned unconditionally, like the metrics datasource — the store being off is a deployment choice rather than a reason to withhold the connection, and an operator whose logs live elsewhere sets this.
Type: string
Default:
"http://127.0.0.1:${toString services.hyperhive.swarm.victorialogs.port}"
Declared by:
services.hyperhive.deploy.grafana.plugins
Grafana plugins to install, as packages. Declarative rather than
installed through the UI, which is the only shape that works here:
plugin management is server-admin scoped, and on an SSO hive
nobody holds that role — users.auto_assign_org_role grants an
org role, and the built-in local admin that does hold server
admin cannot log in because the login form is disabled whenever
SSO is configured.
That is a deliberate pair of decisions rather than an oversight, and this option is the way through it: plugins live in the store and in git, so they survive a container rebuild and a state reset, and the container needs no runtime egress to grafana.com.
⚠️ This list is the ONLY way a plugin reaches this Grafana.
Setting it at all disables upstream’s preinstall mechanism (see
the declarativePlugins comment below), which is what normally
fetches the Drilldown apps on first start — so a plugin left off
this list is absent, not merely un-pinned.
Metrics Drilldown is on by default because this swarm’s Grafana exists to read VictoriaMetrics, and the queryless metrics browser is the part of that people actually reach for.
Its Logs / Traces / Profiles siblings are deliberately NOT here,
and for two different reasons. Traces and Profiles front Tempo
and Pyroscope, which this swarm does not run — a UI for a backend
that does not answer. Logs Drilldown is the subtler one: this
swarm does run a log store, so that argument does not apply
to it, but the app is Loki-only and no configuration here changes
that. Its volume views call /loki/api/v1/index/volume, which
VictoriaLogs does not implement and answers “unsupported path
requested”. Logs are browsed through Explore instead.
Type: list of package
Default:
[
pkgs.grafanaPlugins.grafana-metricsdrilldown-app
pkgs.grafanaPlugins.victoriametrics-logs-datasource
]
Example:
[ pkgs.grafanaPlugins.grafana-piechart-panel ]
Declared by:
services.hyperhive.deploy.grafana.socketDir
Directory holding the unix socket Grafana serves on, shared between the host (where nginx runs) and the container (where Grafana runs).
Fixed, not configurable: the directory’s mode is what keeps the socket private, so it has to be dedicated to this one socket, and a settable path could be pointed at a directory that carries something else.
⚠️ Grafana takes no TCP port at all, and that is the point. Every
swarm service container shares the host’s network namespace, so a
port is a swarm-wide resource that two modules can silently both
claim — which is exactly what happened: Grafana defaulted to
upstream’s 3000, so does the forge, and grafana.<swarm-domain>
served the forge with no bind error and nothing in any log.
A socket has a path, and a path collision is a build-time conflict rather than a runtime coin toss.
Type: string (read only)
Default:
"/run/swarm-grafana"
Declared by:
services.hyperhive.deploy.hive-controller.enable
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 (services.hyperhive.deploy.allSwarmServices)
leaves it off.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.hive-controller.queue.agentCredentialDir
Host directory holding this hive’s agent queue credential: secret
(the OIDC client secret, 0600) and client_id (the client that
secret authenticates, 0644 — it is sent to the token endpoint on
every connection and is not itself a secret).
Both files are written by swarm-bao-queue-agent.service, which also
creates this directory. Named here because nothing else creates it:
the parent /var/lib/hyperhive belongs to hive-c0re.service’s
StateDirectory=, which re-applies its own mode on every start, and a
second declaration of that path is the two-mechanisms-one-path trap
./hive-gateway/default.nix records — so this directory is the unit’s
to make and the parent stays c0re’s.
Absent files mean this hive has no queue credential yet, which is what a swarm looks like before the publisher on the authelia host has run.
Type: absolute path
Default:
"/var/lib/hyperhive/queue-agent"
Declared by:
services.hyperhive.deploy.hive-controller.queue.agentNatsUrl
Where the swarm queue listens, as an agent container on this host reaches it.
Defaults to the queue’s name on every hive. The agent resolves it
through the bridge: on the queue’s own host dnsmasq answers it with
the bridge address, and elsewhere it forwards to the operator’s DNS,
as for the store’s name. ⚠️ Never a loopback address: inside an
agent’s network namespace 127.0.0.1 is the agent, not this host,
and the queue’s certificate names no address anyway.
Null means this hive’s agents have not been given the queue’s address.
Together with
services.hyperhive.swarm.statusPublish.tokenEndpoint it is
what decides whether the harness is handed queue coordinates at all.
Type: null or string
Default:
"tls://${swarm.nats.domain}:${swarm.nats.port}"
Example:
"tls://nats.example.com:4222"
Declared by:
services.hyperhive.deploy.hive-controller.statusPublish.natsUrl
Where the swarm queue listens, as seen from this hive.
Defaults to the queue’s name on every hive. The queue’s own host resolves it locally, and any other hive through the operator’s DNS. TLS only, and by name, since the queue’s certificate carries the name and no address.
A URL alone does not publish. This hive also needs its own store
identity (services.hyperhive.deploy.bao.clientCertFile),
under which hive-c0re reads its hive-<hiveName> client secret
from the swarm’s secret store; swarm-secret-publish, on the host
that runs authelia, puts it there. Without an identity, or with
this set to null, this hive computes its own readiness as always
and offers it to nobody, and the swarm controller reports it
never_reported, which is the honest reading.
Type: null or string
Default:
"tls://${swarm.nats.domain}:${swarm.nats.port}"
Example:
"tls://nats.example.com:4222"
Declared by:
services.hyperhive.deploy.hive-controller.tls.baoHiveIdentityCertFile
This hive’s own store identity. hive-tls-resign presents it to ask
the secret store for the gateway leaf, and swarm-services-cert on a
hive fronting no swarm name presents it for the handshake of the root
fetch.
Its subject has to be
<services.hyperhive.deploy.bao.hiveLeafCommonNamePrefix>-<hiveName>;
that cert-auth role’s policy may issue from this hive’s gateway-leaf
role and nothing else.
Every hive with a self-signed gateway needs it: without it both units
fail, naming this option and
services.hyperhive.deploy.hive-controller.tls.baoHiveIdentityKeyFile.
On the host that runs the store a glue module supplies the leaf as a
mkDefault; on every other host an operator places it.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/hive-leaf.pem"
Declared by:
services.hyperhive.deploy.hive-controller.tls.baoHiveIdentityKeyFile
Private key for
services.hyperhive.deploy.hive-controller.tls.baoHiveIdentityCertFile.
Both or neither — a certificate with no key authenticates nothing.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/hive-leaf-key.pem"
Declared by:
services.hyperhive.deploy.hive-controller.tls.stateDir
Host directory holding the gateway leaf and trust bundle for the
self-signed gateway mode: gateway.pem / gateway-key.pem (the
leaf the store issues and nginx serves) and trust-bundle.pem (the
anchor agents and federation peers trust, the store’s pki root).
Type: string
Default:
"/var/lib/hive-tls"
Declared by:
services.hyperhive.deploy.matrix.enable
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
services.hyperhive.swarm.matrix.*, which every hive
agrees on; this is only the decision to run it here.
Type: boolean
Default:
false
Declared by:
services.hyperhive.deploy.matrix.package
matrix-tuwunel package to run inside the container. Defaults
to nixpkgs’s pkgs.matrix-tuwunel. Override to pin a
specific upstream if you need an unreleased feature.
Type: package
Default:
pkgs.matrix-tuwunel
Declared by:
services.hyperhive.deploy.matrix.ctlBaoClientCertFile
Client certificate the matrix container’s swarm-matrix-ctl presents to the
swarm’s secret store. Its subject must be
services.hyperhive.deploy.bao.matrixCtlCommonName — cert
auth matches on the CN, and the role accepts nothing else.
⚠️ Not the hive’s own leaf, and that is the whole deliverable of
giving this container an identity: the hive’s certificate reads every
agent credential in the swarm, while this one may write a single path. Pointing
this at deploy.bao.clientCertFile would evaluate, deploy and work —
and give away the separation in one line.
No default: a module that guessed would be holding the CA opinion
./swarm-bao.nix deliberately does not hold.
./glue-matrix-ctl-bao-identity.nix points it at the leaf
./glue-bao-tls.nix mints on a host that runs the store
(services.hyperhive.deploy.bao.enable); on any other
homeserver host it is a file the operator places. Never derived from
services.hyperhive.deploy.bao.clientCertFile, which is the
hive’s own reader.
The file and its key are bind-mounted into the container read-only. Co-located in the hive’s filesystem and therefore readable by hive root — accepted: the boundary this buys is identity (no hive process holds the appservice token), not physical isolation.
Type: null or string
Default:
null
Declared by:
services.hyperhive.deploy.matrix.ctlBaoClientKeyFile
Private key for
services.hyperhive.deploy.matrix.ctlBaoClientCertFile.
Both or neither — the unit does not exist unless each is set.
Type: null or string
Default:
null
Declared by:
services.hyperhive.deploy.matrix.ctlPackage
The swarm-matrix-ctl build run inside the matrix container.
⚠️ Named ctlPackage, not folded into package above: that one is
the homeserver, and this is a hyperhive binary that happens to run
beside it. Same split, and same reason, as
services.hyperhive.deploy.nats.authPackage.
Type: package
Default:
hyperhive.packages.${system}.swarm-matrix-ctl
Declared by:
services.hyperhive.deploy.matrix.gui.package
Static web client dist served at gatewayHost’s vhost
(chat.<swarm-domain> by default). Override
to swap fluffychat for hydrogen-web, cinny, element-web, or
an out-of-tree dist — any replacement is mounted at the
sub-domain root with the upstream-default <base href "/">,
no sub-path gymnastics needed.
Type: package
Default:
pkgs.fluffychat-web with a postInstall patch that adds
the three files flutter341.buildFlutterApplication skips.
Declared by:
services.hyperhive.deploy.matrix.maxRequestSize
Maximum size in bytes of a single matrix client request body. Default 20 MB matches the matrix-spec recommendation for media uploads + the upstream tuwunel default.
This is the only limit to set: the gateway’s own body cap is derived from it, with headroom, so the homeserver stays the one that rejects an oversized upload.
Type: positive integer, meaning >0
Default:
20000000
Declared by:
services.hyperhive.deploy.matrix.openFirewall
Open httpPort in the host firewall. Off by default
(secure-by-default): hive-c0re and agent containers reach the
homeserver at gatewayHost’s vhost (chat.<swarm-domain> by
default) via the gateway, so the open port only matters for
direct access to httpPort from outside the host. Flip to true when announcing
the homeserver to other hives or when an external matrix
client needs to reach the client-server API directly.
Note: federation (the matrix-spec well-known port 8448) is
intentionally not opened here. tuwunel serves the federation
API on the same httpPort as the client-server API by
default; reaching it on 8448 requires either binding tuwunel
to that port explicitly OR a reverse-proxy + .well-known/ matrix/server delegation, neither of which lives in this
module. Add that proxy config alongside whatever serves your
dashboard or forge on 443.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.matrix.sso.clientSecretFile
Path inside the matrix container holding the client secret’s plaintext.
A path, never a value: an OIDC client secret has two holders in two containers (authelia keeps a hash, this homeserver needs the plaintext), and a literal written here would be rendered into the world-readable nix store.
Set to /var/lib/tuwunel-oidc/<client id>.secret wherever the
homeserver runs. swarm-bao-matrix-oidc writes the secret here
from the swarm secret store, whichever path this names. The id
this pairs with is swarm.matrix.sso.clientId, which is
swarm-wide because authelia’s host registers it.
Type: null or string
Default:
null
Example:
"/var/lib/tuwunel-oidc/tuwunel.secret"
Declared by:
services.hyperhive.deploy.matrix.trustedServers
List of trusted matrix servers (homeservers whose signing keys this server will fetch identity-server-style). Empty by default — federation is enabled at the protocol level but no peer is trusted until listed here, so the homeserver is effectively closed until the operator declares hive peers explicitly.
Type: list of string
Default:
[ ]
Example:
[
"matrix.org"
]
Declared by:
services.hyperhive.deploy.nats.enable
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.
Type: boolean
Default:
false
Declared by:
services.hyperhive.deploy.nats.authBaoClientCertFile
Client certificate the auth-callout responder presents to the swarm’s
secret store to read the callout keys, its own OIDC client secret and
agent queue credentials, and that swarm-bao-nats-callout-xkey
presents to read the callout keys’ public halves. Its subject must be
services.hyperhive.deploy.bao.natsAuthCommonName.
Required when deploy.nats.enable is set; unset fails at eval.
./glue-nats-auth-bao-identity.nix points it at the leaf
./glue-bao-tls.nix mints on a host that runs the store
(services.hyperhive.deploy.bao.enable); on any other queue
host it is a file the operator places. Never derived from
services.hyperhive.deploy.bao.clientCertFile, which is the
hive’s own reader. Set to a file that does
not exist, swarm-nats-auth-secrets and swarm-bao-nats-callout-xkey
fail, and the queue’s server does not start without the xkey.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/nats-auth.pem"
Declared by:
services.hyperhive.deploy.nats.authBaoClientKeyFile
Private key for services.hyperhive.deploy.nats.authBaoClientCertFile.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/nats-auth-key.pem"
Declared by:
services.hyperhive.deploy.nats.authPackage
The auth-callout responder package.
⚠️ Named authPackage, not package, on purpose: this module
deliberately has no package option for the NATS server
itself, because upstream’s services.nats resolves
pkgs.nats-server on its own — see the note above
options.services.hyperhive.swarm.nats. A bare package here
would read as “the NATS package” and mean something else
entirely.
Type: package
Default:
hyperhive.packages.${system}.swarm-nats-auth
Declared by:
services.hyperhive.deploy.nats.baoClientCertFile
Client certificate swarm-bao-nats-tls presents to the swarm’s
secret store when it asks for the queue’s TLS leaf. Its subject must
be services.hyperhive.deploy.bao.natsCommonName: cert auth
matches on the CN, and that role’s policy may issue from
pki/issue/swarm-nats and nothing else.
No default. ./glue-nats-bao-identity.nix points it at the leaf
./glue-bao-tls.nix mints on a host that runs the store
(services.hyperhive.deploy.bao.enable). On a queue host
without the store, it is a file the operator copies from the store’s
host. Never derived from
services.hyperhive.deploy.bao.clientCertFile, which is the
hive’s own reader.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/nats.pem"
Declared by:
services.hyperhive.deploy.nats.baoClientKeyFile
Private key for services.hyperhive.deploy.nats.baoClientCertFile.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/nats-key.pem"
Declared by:
services.hyperhive.deploy.review-classifier.enable
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
services.hyperhive.deploy.allSwarmServices is set and this
host has the classifier’s store identity (the pair
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…”.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.review-classifier.package
The review classifier daemon package.
Type: package
Default:
hyperhive.packages.${system}.swarm-review-classifier
Declared by:
services.hyperhive.deploy.singleHostSwarm
Run the whole swarm on this host. Turning this on asserts the
toggles that an all-on-one-box deployment implies: the swarm’s
shared services
(services.hyperhive.deploy.allSwarmServices), the swarm
controller (services.hyperhive.deploy.swarm-controller.enable), and the
host’s /etc/hosts entries for the names this hive serves
(services.hyperhive.gateway.localHostsEntry) — with no real DNS
for those names, the operator is browsing them from the same box
that answers for them.
Off by default, and that is the load-bearing part. A swarm’s services and its hives can live on different hosts, and a host has no way to tell which ones it is meant to be — so this is an operator saying “this is that box”, never something inferred. Turn it on for a dev box or a single-hive swarm and get a working deployment with no further configuration; leave it off and every swarm-level artifact is operator-provided.
Each toggle it asserts can still be set explicitly, which wins — so “all local except X” needs no new option.
Type: boolean
Default:
false
Example:
true
Declared by:
services.hyperhive.deploy.swarm-controller.enable
Run the swarm-controller daemon on this host.
Off by default and deliberately not derived from
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.
Type: boolean
Default:
false
Declared by:
services.hyperhive.deploy.swarm-controller.package
swarm-controller package. Wired by default from this flake’s own
package set (see flake.nix); override to run a different build.
Type: package
Default:
hyperhive.packages.${system}.swarm-controller
Declared by:
services.hyperhive.deploy.swarm-controller.authBridgeUrl
Where swarm-authelia-bridge (the only writer of authelia’s
users database) answers. The default is the /bridge/ location
on the authelia vhost, the same address from every host whether
or not it runs swarm-authelia; the daemon appends /requests.
No new credential to configure: the bearer token presented to
the bridge is minted from THIS daemon’s own existing queue OIDC
identity — its endpoints stay in swarm.controller.queue, its secret is
read from the swarm’s secret store — “one identity per principal”
already covers it. null means no agent-identity support:
CreateIdentity jobs fail with a clear “no auth bridge
configured here” error rather than the daemon refusing to
start, the same graceful-absence shape forge access has.
Type: null or string
Default:
"${services.hyperhive.swarm.authelia.url}/bridge"
Example:
"https://auth.example.com/bridge"
Declared by:
services.hyperhive.deploy.swarm-controller.baoClientCertFile
Certificate this daemon presents to the swarm’s secret store. Its
subject has to match
services.hyperhive.deploy.bao.controllerCommonName, which is
what the store’s cert-auth role matches on.
Distinct from services.hyperhive.deploy.bao.clientCertFile on
purpose, and not an oversight: that one is this host as a reader and
carries the hive’s name, while the controller’s policy lets it create
roles for every hive. One certificate serving both would hand that power
to whatever else reads the store here.
Defaulted by glue-controller-bao-identity.nix where this deployment
mints its own; elsewhere the leaf is issued out of band and named here.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-controller/bao-client.pem"
Declared by:
services.hyperhive.deploy.swarm-controller.baoClientKeyFile
Private key for services.hyperhive.deploy.swarm-controller.baoClientCertFile.
Both or neither — a certificate with no key authenticates nothing.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-controller/bao-client-key.pem"
Declared by:
services.hyperhive.deploy.swarm-controller.configOrgAvatarPng
PNG uploaded once as the agent-configs Forgejo org’s avatar by
the controller’s swarm-wide forge-objects pass (one-shot,
marker-guarded — delete forge-config-org-avatar-set under the
controller’s state directory to force a re-upload after changing
this). Defaults (null) to the bundled agent-configs.png from
services.hyperhive.c0re.assets. Set this to override just
the org avatar without replacing the whole assets package.
Type: null or absolute path
Default:
null
Declared by:
services.hyperhive.deploy.swarm-controller.hiveClientCaFile
Authority whose leaves are hive client certificates, so that this daemon can create each hive’s cert-auth role. The store matches a presented certificate against the role’s copy of this, which is why the role carries the authority itself rather than a path to it.
The same material as services.hyperhive.deploy.bao.clientCaFile,
named separately because that option is the store’s: it says which
readers the store trusts, on the host that runs the store. A controller
runs anywhere, so it names its own copy, and a glue module supplies this
as a mkDefault where the two are co-located.
Public material — a certificate authority, not a key — so unlike every other credential here it leaks nothing. It stays a path anyway, because the file it names is the one the store already installs.
null leaves hive roles uncreated, which is the state a swarm is in
before anyone has onboarded a hive.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/ca.pem"
Declared by:
services.hyperhive.deploy.swarm-controller.matrixHomeserverUrl
Client-server API base of the swarm’s homeserver. The controller
creates each agent’s own matrix account there, with the swarm’s
appservice token, and stores its token where the agent reads it.
null leaves agents with no matrix account: the mint node fails,
naming this option’s variable, and the agent is deployed anyway.
Also the swarm-wide default homeserver for PUT .../matrix-accounts/{account} requests that omit their own
homeserver — see that route’s own doc comment
(swarm-controller/src/matrix_account.rs) for why the field is
optional in token mode and what omitting it currently resolves to.
That route does not consult it yet.
Type: null or string
Default:
"https://${services.hyperhive.swarm.matrix.gatewayHost}"
Example:
"https://matrix.example.org"
Declared by:
services.hyperhive.deploy.swarm-controller.socketPath
Unix socket the daemon serves on, and the path the gateway’s nginx proxies to.
The directory is the access control here, not the socket mode:
the socket itself is 0666 (nginx runs as another user, and
connect(2) needs write), exactly as hive-c0re publishes the
per-agent sockets. What keeps that safe is that the directory holds
exactly one socket and is traverse-only (0751) for everyone else.
Moving this path under a directory that carries anything else —
/run/hyperhive, which holds the host admin socket, above all —
exposes whatever else lives there to the same reachability.
Changing this therefore means re-checking what else lives in the new directory, not just the daemon.
Type: string (read only)
Default:
"/run/swarm-controller/controller.sock"
Declared by:
services.hyperhive.deploy.swarm-controller.swarmctlPackage
swarmctl package — the swarm operator’s CLI, installed on this
host alongside the daemon and wrapped with the paths it needs.
A separate option from package rather than a second binary in
the same derivation: the CLI runs as root and acts directly,
the daemon runs unprivileged and serves a socket, and pinning one
without the other is a thing an operator may legitimately want.
Type: package
Default:
hyperhive.packages.${system}.swarmctl
Declared by:
services.hyperhive.deploy.swarm-otel.enable
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:
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
services.hyperhive.swarm.otel.domain.
Type: boolean
Default:
false
Declared by:
services.hyperhive.deploy.swarm-otel.clientSecretFile
Path, inside this collector’s container, to its OIDC client secret.
null means it holds no credential: it still exports, and the
authenticated destinations refuse it. Set automatically where
authelia is co-located; a deployment that places authelia elsewhere
points this at a file it delivers itself.
⚠️ A path, never a value — a secret interpolated into a nix expression renders world-readable into the store.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-otel-oidc/swarm-collector.secret"
Declared by:
services.hyperhive.deploy.swarm-secret-publisher.enable
Publish the OIDC client secrets this host mints into the swarm’s secret store, so a hive that does not run authelia can read its own and its agents’ credentials and a swarm service or the controller can read its own — from wherever it runs, this host included.
Defaults to whether this host mints the OIDC secrets (set by
glue-secret-publisher-authelia.nix), which is the only half of the
question that is a property of this host.
⚠️ Deliberately not deploy.bao.enable. That asks whether the
store stands here, and a publisher beside a remote store, holding a
leaf issued out of band, is a deployment this exists to serve —
defaulting on co-location would leave exactly that shape silently
publishing nothing. Whether the wiring is complete is the client
identity’s job (see baoClientCertFile), not this option’s.
Turning it off leaves every hive but this one without its agents’ credential, every hive unable to publish its status, the swarm controller unable to start, the swarm’s Grafana without any login at all, its collector pushing unauthenticated, the queue’s responder unable to start, the homeserver unable to start, and the forge’s login source without its secret. Each secret has exactly one route and this is the producer’s end of it, so the honest reason to set it false is a deployment delivering those secrets by some other mechanism it owns.
Type: boolean
Default:
false
Declared by:
services.hyperhive.deploy.swarm-secret-publisher.baoClientCertFile
Client certificate this publisher presents to the store. Its subject
must be services.hyperhive.deploy.bao.secretPublisherCommonName
— cert auth matches on the CN, and the role accepts nothing else.
No default: a module that guessed would be holding the CA opinion ./swarm-bao.nix deliberately does not hold. ./glue-secret-publisher-bao-identity.nix points it at the leaf ./glue-bao-tls.nix mints, where this host mints one.
Type: null or string
Default:
null
Declared by:
services.hyperhive.deploy.swarm-secret-publisher.baoClientKeyFile
Private key for services.hyperhive.deploy.swarm-secret-publisher.baoClientCertFile.
Both or neither — the unit does not exist unless each is set.
Type: null or string
Default:
null
Declared by:
services.hyperhive.deploy.swarm-ui.package
Static build of the swarm UI. nginx serves this store path directly — there is no server-side component beyond the controller’s own API.
Wired by default from this flake’s own package set (see
flake.nix), the same way deploy.swarm-controller.package is. There
is deliberately no overlay in this project, so a
pkgs.swarm-ui default here would name an attribute that does
not exist on any real deployment.
Type: package
Default:
hyperhive.packages.${system}.swarm-ui
Declared by:
services.hyperhive.deploy.victorialogs.enable
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.
Type: boolean
Default:
false
Declared by:
services.hyperhive.deploy.victorialogs.package
VictoriaLogs package to run.
Type: package
Default:
pkgs.victorialogs
Declared by:
services.hyperhive.deploy.victorialogs.authBaoClientCertFile
Client certificate swarm-logs-auth presents to the swarm’s secret store
to read agents’ queue secrets. Its subject must be
services.hyperhive.deploy.bao.logsAuthCommonName.
Required when deploy.victorialogs.enable is set; unset fails at eval.
./glue-logs-auth-bao-identity.nix points it at the leaf
./glue-bao-tls.nix mints on a host that runs the store; on any other
log-store host it is a file the operator places.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/logs-auth.pem"
Declared by:
services.hyperhive.deploy.victorialogs.authBaoClientKeyFile
Private key for services.hyperhive.deploy.victorialogs.authBaoClientCertFile.
A path, never a value.
Type: null or string
Default:
null
Example:
"/var/lib/swarm-bao-pki/logs-auth-key.pem"
Declared by:
services.hyperhive.deploy.victorialogs.authBurst
Requests a client address may make above
services.hyperhive.deploy.victorialogs.authRate before nginx
answers 403, served without delay.
Type: positive integer, meaning >0
Default:
500
Declared by:
services.hyperhive.deploy.victorialogs.authPackage
The swarm-logs-auth package: the gateway’s auth_request responder
that checks an agent’s swarm-agent.<agent>.<secret> bearer on
/select/logsql/ against the secret store.
Type: package
Default:
hyperhive.packages.${system}.swarm-logs-auth
Declared by:
services.hyperhive.deploy.victorialogs.authRate
nginx limit_req rate, per client address, of /select/logsql/
requests carrying a swarm-agent. bearer, which nginx checks with
swarm-logs-auth. Each such request that the responder has not granted
within services.hyperhive.deploy.victorialogs.authVerdictTtl
costs a secret store login and read, whether the bearer is right or not.
Counts every agent query, granted or not, and is keyed by client address, so every agent on one host shares one budget. The default covers about a hundred agents on a host cold-starting at once, each costing one store login and read for its first query. Requests over the rate and its burst are answered 403.
Type: string
Default:
"50r/s"
Example:
"30r/m"
Declared by:
services.hyperhive.deploy.victorialogs.authVerdictTtl
Seconds swarm-logs-auth grants an agent bearer it has verified again
without reading the secret store. A denial is never remembered.
This is also how long a re-minted or deleted queue secret keeps working
at the log store’s query route after its last successful check. 0
checks the store on every query.
Type: unsigned integer, meaning >=0
Default:
60
Declared by:
services.hyperhive.deploy.victorialogs.retentionPeriod
How long log data is kept.
Deliberately far shorter than the metrics store’s retention: logs are orders of magnitude larger per unit of time, and their value decays much faster. A log line answers “what happened during that incident”; a metric answers “is this worse than last quarter”.
Type: string
Default:
"30d"
Example:
"90d"
Declared by:
services.hyperhive.deploy.victoriametrics.enable
Run the swarm’s metrics store on this host.
Paired with
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.
Type: boolean
Default:
false
Declared by:
services.hyperhive.deploy.victoriametrics.package
VictoriaMetrics package to run.
Type: package
Default:
pkgs.victoriametrics
Declared by:
services.hyperhive.deploy.victoriametrics.retentionPeriod
How long samples are kept.
Deliberately a high default rather than a required option: the two failure directions are not symmetric. Too long fills a disk, which is visible and recoverable by lowering this; too short destroys history, silently and permanently. So the safe default is generous and an operator lowers it once they have measured how fast this swarm actually accumulates data.
Type: string
Default:
"5y"
Example:
"90d"
Declared by:
services.hyperhive.deploy.wireguard.enable
Enable the WireGuard inter-hive mesh. When true, a wg-hive
interface is brought up connecting to all swarm peers that
declare a wireguardPublicKey. Requires
privateKeyFile to be set.
Type: boolean
Default:
false
Declared by:
services.hyperhive.deploy.wireguard.address
IP address (with prefix) of this host on the WireGuard mesh.
Use a /24 (or broader) prefix so the routing table covers all
peer /32 routes. Example: "10.100.0.1/24" for a 256-host mesh.
Type: string
Default:
""
Example:
"10.100.0.1/24"
Declared by:
services.hyperhive.deploy.wireguard.listenPort
UDP port the local WireGuard interface listens on. Must be reachable from peer hosts when they initiate the tunnel. Default: 51820 (standard WireGuard port).
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
51820
Declared by:
services.hyperhive.deploy.wireguard.persistentKeepalive
Seconds between keepalive packets sent to each peer. Useful when this host (or a peer) is behind NAT — keeps the UDP hole open. Set to null to disable. Default: 25 seconds.
Type: null or signed integer
Default:
25
Example:
25
Declared by:
services.hyperhive.deploy.wireguard.privateKeyFile
Path to the host’s WireGuard private key file. The file must
be readable by root and should have mode 0400. Generate with
wg genkey > /etc/wireguard/hive.key. Required when
deploy.wireguard.enable = true.
Type: null or absolute path
Default:
null
Example:
"/etc/wireguard/hive.key"
Declared by: