Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bd5c51e2e | ||
|
|
d7a471043b | ||
|
|
97a7b518ea | ||
|
|
585269b8a3 |
15 changed files with 112 additions and 107 deletions
|
|
@ -24,7 +24,7 @@ the root, so setting the swarm CA up is an operator action rather than
|
|||
something a host assumes. Turn it on for an all-on-one-host deployment
|
||||
and the hierarchy costs no configuration.
|
||||
|
||||
It defaults from `services.hyperhive.enableAllLocalDefaults`, the single
|
||||
It defaults from `services.hyperhive.deploy.singleHostSwarm`, the single
|
||||
switch that says "this box is the whole deployment".
|
||||
|
||||
**A hive given neither artifact keeps the self-signed CA it has always
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ scraped; otherwise no secret is needed and none is placed.
|
|||
### Minting the queue's callout nkeys
|
||||
|
||||
`nats.autoGenerateCallout` mints both keypairs on the host before the queue
|
||||
starts. It is on by default only under `enableAllLocalDefaults` — the one
|
||||
starts. It is on by default only under `singleHostSwarm` — the one
|
||||
topology where the queue, its responder and the operator are the same person. On
|
||||
every other topology, mint them yourself:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,24 @@
|
|||
# Swarm-wide services
|
||||
|
||||
Some things exist once per **swarm**, not once per hive: the forge, the
|
||||
matrix homeserver, the SSO provider, the CA. Two options say where the
|
||||
optional ones live, and everything else derives:
|
||||
Some things exist once per **swarm** rather than once per hive. Two
|
||||
options say where the optional ones live, and everything else derives:
|
||||
|
||||
```nix
|
||||
services.hyperhive.enableAllLocalDefaults = true; # everything on this box
|
||||
services.hyperhive.deploy.singleHostSwarm = true; # everything on this box
|
||||
# or, for a dedicated services host with hives elsewhere:
|
||||
services.hyperhive.swarm.enableRequiredServices = true;
|
||||
services.hyperhive.deploy.allSwarmServices = true;
|
||||
```
|
||||
|
||||
`enableAllLocalDefaults` is the all-on-one-box switch: it defaults both
|
||||
`swarm.enableRequiredServices` (the shared services run here) and
|
||||
`swarm.ca.autoConfigure` (the swarm CA is generated here). Each derived
|
||||
toggle can still be set on its own, so "all local except X" needs no
|
||||
further option.
|
||||
**`deploy.allSwarmServices` is what "the swarm's shared services run
|
||||
here" means: every once-per-swarm service that is *optional* takes its
|
||||
`enable` from it.** That is the whole rule, stated once — the per-service
|
||||
sections below do not repeat it, so a service that stops deriving is a
|
||||
visible difference rather than one more paragraph saying the same thing.
|
||||
|
||||
`singleHostSwarm` is the all-on-one-box switch above it: it defaults
|
||||
both `deploy.allSwarmServices` and `swarm.ca.autoConfigure` (the swarm CA
|
||||
is generated here). Each derived toggle can still be set on its own,
|
||||
which wins, so "all local except X" needs no further option.
|
||||
|
||||
**Both default to off**, and that is deliberate: a host cannot tell
|
||||
whether it is meant to be the swarm's service host, so this is an
|
||||
|
|
@ -33,10 +37,10 @@ Those two options are what makes the difference between deployments, so
|
|||
the shapes worth naming are the ones they produce:
|
||||
|
||||
- **All-local.** Everything on one machine:
|
||||
`enableAllLocalDefaults = true`. Setup is automatic apart from
|
||||
`singleHostSwarm = true`. Setup is automatic apart from
|
||||
choosing a domain and creating the first user.
|
||||
- **Services on the swarm controller host.**
|
||||
`swarm.enableRequiredServices = true` there; the required services
|
||||
`deploy.allSwarmServices = true` there; the required services
|
||||
deploy together on that host, with hives elsewhere.
|
||||
- **Fully spread out.** One container / VM / machine per service,
|
||||
somewhere.
|
||||
|
|
@ -64,8 +68,7 @@ One authelia per swarm, in a `swarm-authelia` container, at
|
|||
provider, differentiated by roles and claims rather than by mechanism —
|
||||
there is one IdP and one auth path.
|
||||
|
||||
- **`deploy.authelia`** — run the container here. Defaults from
|
||||
`swarm.enableRequiredServices`.
|
||||
- **`deploy.authelia`** — run the container here.
|
||||
- **`swarm.authelia.url`** — where clients are sent to authenticate.
|
||||
Present on **every** hive, defaulting to this host's own instance only
|
||||
when this module is the thing running it; otherwise `null`, and a hive
|
||||
|
|
@ -98,10 +101,8 @@ one Grafana, in two containers at `metrics.<swarm-domain>` and
|
|||
`grafana.<swarm-domain>`. Two containers rather than one so Grafana can
|
||||
be restarted or broken without taking the time-series database with it.
|
||||
|
||||
Both follow `swarm.enableRequiredServices` like authelia and matrix, so
|
||||
the swarm's service host gets them with everything else. They derive
|
||||
together: a store with no UI is unreadable and a UI with no store is
|
||||
empty. To run one without the other, set it directly:
|
||||
They derive together: a store with no UI is unreadable and a UI with no
|
||||
store is empty. To run one without the other, set it directly:
|
||||
|
||||
```nix
|
||||
services.hyperhive.deploy.victoriametrics.enable = true;
|
||||
|
|
@ -132,9 +133,8 @@ the collector is the only intended writer.
|
|||
### Logs (VictoriaLogs)
|
||||
|
||||
The swarm's service containers ship their journals to one VictoriaLogs at
|
||||
`logs.<swarm-domain>`, behind the same SSO as everything else. It follows
|
||||
`swarm.enableRequiredServices` too, and the collector below is what writes
|
||||
to it.
|
||||
`logs.<swarm-domain>`, behind the same SSO as everything else. The
|
||||
collector below is what writes to it.
|
||||
|
||||
**Reading them.** Open Grafana, pick **Explore**, and choose the
|
||||
`VictoriaLogs` datasource — it is provisioned for you. Grafana's *Logs
|
||||
|
|
@ -160,9 +160,8 @@ and exports to `otel.endpoint`, doing both when both are configured. It
|
|||
also holds the upstream credential, which is why no hive and no agent
|
||||
needs one.
|
||||
|
||||
It follows `swarm.enableRequiredServices` like the services above, in a
|
||||
`swarm-otel` container. Its `swarm.otel.port` defaults to `4319` rather
|
||||
than OTLP's usual `4318`, which the hive tier already uses — swarm
|
||||
It runs in a `swarm-otel` container. Its `swarm.otel.port` defaults to
|
||||
`4319` rather than OTLP's usual `4318`, which the hive tier uses — swarm
|
||||
containers share the host's network namespace, so two collectors on one
|
||||
port is a coin toss at runtime rather than an error at build time.
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ answers for one host. This one is the view *across* hives.
|
|||
services.hyperhive.deploy.swarm-ui.enable = true; # defaults to deploy.swarm-controller.enable
|
||||
```
|
||||
|
||||
Derived from the controller rather than from `enableRequiredServices`:
|
||||
Derived from the controller rather than from `allSwarmServices`:
|
||||
the UI is a view onto the controller's state and reaches it over that
|
||||
daemon's socket, so the host that runs the controller is the host that
|
||||
can serve the UI. A hive that merely *uses* a swarm has nothing to serve.
|
||||
|
|
|
|||
|
|
@ -110,6 +110,25 @@ in
|
|||
[ "services" "hyperhive" "swarm" "victorialogs" "retentionPeriod" ]
|
||||
[ "services" "hyperhive" "deploy" "victorialogs" "retentionPeriod" ]
|
||||
)
|
||||
|
||||
# The switch over all of the above, and the name changes with the path
|
||||
# because the old one described the wrong subject: those services are
|
||||
# required of the SWARM, while the option says whether THIS host runs
|
||||
# them. `allSwarmServices` is mara's own phrasing of what it means.
|
||||
(lib.mkRenamedOptionModule
|
||||
[ "services" "hyperhive" "swarm" "enableRequiredServices" ]
|
||||
[ "services" "hyperhive" "deploy" "allSwarmServices" ]
|
||||
)
|
||||
|
||||
# The mode above that one. It sat at the TOP of `services.hyperhive`,
|
||||
# which is the same defect one tier up: that namespace is everything
|
||||
# about hyperhive, not the settings of a single hive. The new name says
|
||||
# what the mode asserts — the whole swarm runs on this host — instead of
|
||||
# naming its mechanism.
|
||||
(lib.mkRenamedOptionModule
|
||||
[ "services" "hyperhive" "enableAllLocalDefaults" ]
|
||||
[ "services" "hyperhive" "deploy" "singleHostSwarm" ]
|
||||
)
|
||||
];
|
||||
|
||||
# ⚠️ `deploy.forgejo` is declared in ./hive-ci.nix, not here, and it is the
|
||||
|
|
@ -139,9 +158,8 @@ in
|
|||
description = ''
|
||||
Run the swarm's metrics store on this host.
|
||||
|
||||
Derives from
|
||||
{option}`services.hyperhive.swarm.enableRequiredServices` together
|
||||
with {option}`services.hyperhive.deploy.grafana.enable`: a store
|
||||
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.
|
||||
|
|
@ -154,10 +172,8 @@ in
|
|||
description = ''
|
||||
Run the swarm's log store on this host.
|
||||
|
||||
Derives from
|
||||
{option}`services.hyperhive.swarm.enableRequiredServices` for the
|
||||
same reason as the metrics pair above: a hive that is not the
|
||||
service host is a *client* of this store, not a second one.
|
||||
A hive that is not the service host is a *client* of this store,
|
||||
not a second one.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -167,14 +183,10 @@ in
|
|||
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, so
|
||||
this is asserted from
|
||||
{option}`services.hyperhive.swarm.enableRequiredServices`
|
||||
alongside the other once-per-swarm services.
|
||||
host. A swarm has one store and it has to exist somewhere.
|
||||
|
||||
That assertion is a `mkDefault`, which is what keeps *where* the
|
||||
store runs a separate question from *that* it runs: set this
|
||||
directly to put the store on a host of its own, and clients
|
||||
*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.
|
||||
|
|
@ -193,9 +205,7 @@ in
|
|||
example = true;
|
||||
description = ''
|
||||
Run the swarm's authelia in a `swarm-authelia` container on this
|
||||
host. {option}`services.hyperhive.swarm.enableRequiredServices`
|
||||
turns this on — a swarm has one SSO provider, and that says it
|
||||
lives here.
|
||||
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
|
||||
|
|
@ -211,10 +221,8 @@ in
|
|||
description = ''
|
||||
Run the **swarm's** telemetry collector on this host.
|
||||
|
||||
Derives from
|
||||
{option}`services.hyperhive.swarm.enableRequiredServices` with the
|
||||
metrics pair it feeds: a swarm has one of these, and it belongs
|
||||
wherever the shared services live rather than on every hive.
|
||||
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:
|
||||
|
|
@ -233,10 +241,8 @@ in
|
|||
Run the swarm's matrix homeserver — matrix-tuwunel, in a
|
||||
`hive-matrix` container — on this host.
|
||||
|
||||
Derives from
|
||||
{option}`services.hyperhive.swarm.enableRequiredServices` with
|
||||
the other once-per-swarm services. Set it here directly to put
|
||||
the homeserver somewhere other than the host holding the rest.
|
||||
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
|
||||
|
|
@ -280,10 +286,8 @@ in
|
|||
Serve the swarm UI from this host.
|
||||
|
||||
Derived from
|
||||
{option}`services.hyperhive.deploy.swarm-controller.enable` rather
|
||||
than from
|
||||
{option}`services.hyperhive.swarm.enableRequiredServices`: the UI
|
||||
is a view onto the controller's state and reaches it over that
|
||||
{option}`services.hyperhive.deploy.swarm-controller.enable`: 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
|
||||
host that can serve the UI. A hive that merely *uses* a swarm has
|
||||
nothing to serve here.
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ in
|
|||
DNS shouldn't have a stale `/etc/hosts` entry sticking
|
||||
around. Requires `services.hyperhive.domain` to be set.
|
||||
|
||||
`services.hyperhive.enableAllLocalDefaults` turns this on as
|
||||
`services.hyperhive.deploy.singleHostSwarm` turns this on as
|
||||
part of saying "this box is the whole deployment": that mode
|
||||
means there is no real DNS for these names and the operator is
|
||||
browsing them from the host itself. Set it here explicitly to
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
# `enableAllLocalDefaults` is declared in ./local-defaults.nix, with
|
||||
# `singleHostSwarm` is declared in ./local-defaults.nix, with
|
||||
# the values it asserts. It is a deployment mode rather than a setting
|
||||
# this module's options read, so it lives with its consequences.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# The all-local deployment mode.
|
||||
#
|
||||
# `enableAllLocalDefaults` is a *mode*, not a default other options read:
|
||||
# `singleHostSwarm` is a *mode*, not a default other options read:
|
||||
# it says "this box is the whole deployment" and then asserts the values
|
||||
# that follow from that. mara, on the issue: it is "more of a deployment
|
||||
# mode via settings set, less a default setting".
|
||||
|
|
@ -23,7 +23,7 @@ let
|
|||
cfg = config.services.hyperhive;
|
||||
in
|
||||
{
|
||||
options.services.hyperhive.enableAllLocalDefaults = lib.mkOption {
|
||||
options.services.hyperhive.deploy.singleHostSwarm = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
|
|
@ -31,7 +31,7 @@ in
|
|||
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.swarm.enableRequiredServices`), the swarm
|
||||
(`services.hyperhive.deploy.allSwarmServices`), the swarm
|
||||
CA (`services.hyperhive.swarm.ca.autoConfigure`), the swarm
|
||||
controller (`services.hyperhive.deploy.swarm-controller.enable`), and the
|
||||
host's `/etc/hosts` entries for the names this hive serves
|
||||
|
|
@ -69,17 +69,23 @@ in
|
|||
# every agent at its own netns. That guard already existing is what
|
||||
# makes turning this on by default safe; without it this line would
|
||||
# break every agent's access to the forge.
|
||||
config.services.hyperhive.gateway.localHostsEntry = lib.mkDefault cfg.enableAllLocalDefaults;
|
||||
config.services.hyperhive.gateway.localHostsEntry = lib.mkDefault cfg.deploy.singleHostSwarm;
|
||||
|
||||
# Out of the `swarm` attrset below, because it is a `deploy.*` option now
|
||||
# (./deploy.nix): "does THIS host run the swarm's services" is a per-host
|
||||
# decision. Written as a path rather than folded into a second
|
||||
# `config.services.hyperhive.deploy = { … }` attrset, for the same reason
|
||||
# the ⚠️ below gives about `swarm`.
|
||||
config.services.hyperhive.deploy.allSwarmServices = lib.mkDefault cfg.deploy.singleHostSwarm;
|
||||
|
||||
config.services.hyperhive.swarm = {
|
||||
enableRequiredServices = lib.mkDefault cfg.enableAllLocalDefaults;
|
||||
ca.autoConfigure = lib.mkDefault cfg.enableAllLocalDefaults;
|
||||
ca.autoConfigure = lib.mkDefault cfg.deploy.singleHostSwarm;
|
||||
# The queue's auth-callout nkeys. Generating them is safe exactly
|
||||
# when one operator owns both the queue and its responder, which is
|
||||
# what this mode asserts. On any other topology the seeds have to
|
||||
# reach whoever runs the responder, and minting them here would move
|
||||
# that hand-off somewhere less visible rather than removing it.
|
||||
nats.autoGenerateCallout = lib.mkDefault cfg.enableAllLocalDefaults;
|
||||
nats.autoGenerateCallout = lib.mkDefault cfg.deploy.singleHostSwarm;
|
||||
# The controller's queue coordinates. Co-location is what makes these
|
||||
# derivable at all — loopback only reaches the queue when the queue is
|
||||
# here, and the minted client secret only exists on the host authelia
|
||||
|
|
@ -101,10 +107,10 @@ in
|
|||
# The *requirement* stays in `swarm-controller.nix` as an assertion:
|
||||
# needing a queue is the controller's own property in every topology,
|
||||
# and only the convenience is local.
|
||||
controller.queue.natsUrl = lib.mkIf cfg.enableAllLocalDefaults (
|
||||
controller.queue.natsUrl = lib.mkIf cfg.deploy.singleHostSwarm (
|
||||
lib.mkDefault "nats://127.0.0.1:${toString config.services.hyperhive.swarm.nats.port}"
|
||||
);
|
||||
controller.queue.clientSecretFile = lib.mkIf cfg.enableAllLocalDefaults (
|
||||
controller.queue.clientSecretFile = lib.mkIf cfg.deploy.singleHostSwarm (
|
||||
lib.mkDefault "${config.services.hyperhive.swarm.authelia.hostClientSecretDir}/swarm-controller.secret"
|
||||
);
|
||||
};
|
||||
|
|
@ -113,7 +119,7 @@ in
|
|||
# option stays `default = false` precisely because running it is a
|
||||
# statement about swarm topology — but "this box is the whole
|
||||
# deployment" IS that statement, and it is the one shape where the
|
||||
# answer isn't ambiguous. Deriving it from `enableRequiredServices`
|
||||
# answer isn't ambiguous. Deriving it from `allSwarmServices`
|
||||
# instead would be wrong: a hive in a larger swarm can legitimately
|
||||
# want the shared services without being the host that controls them.
|
||||
#
|
||||
|
|
@ -122,5 +128,5 @@ in
|
|||
# the per-host fact `swarm.*` may not carry. The ⚠️ collision note above
|
||||
# does not apply here — that one is about two definitions of `swarm`
|
||||
# itself, and this is a different top-level path.
|
||||
config.services.hyperhive.deploy.swarm-controller.enable = lib.mkDefault cfg.enableAllLocalDefaults;
|
||||
config.services.hyperhive.deploy.swarm-controller.enable = lib.mkDefault cfg.deploy.singleHostSwarm;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# - the CLIENT pointer (`url`) exists on every hive, because a hive
|
||||
# that doesn't run authelia still has to know where to send people.
|
||||
# - the CONTAINER only exists where the swarm's shared services live.
|
||||
# `swarm.enableRequiredServices` asserts this module's `enable`
|
||||
# `deploy.allSwarmServices` asserts this module's `enable`
|
||||
# (see ./swarm-required-services.nix); a hive is a client by default.
|
||||
#
|
||||
# Operator and agents are both subjects of the same provider,
|
||||
|
|
@ -992,7 +992,7 @@ in
|
|||
#
|
||||
# Gated on the collector's `enable` as well, and that second condition is
|
||||
# what makes the loopback address honest. Both services default from
|
||||
# `swarm.enableRequiredServices` — but `mkDefault` is an invitation to
|
||||
# `deploy.allSwarmServices` — but `mkDefault` is an invitation to
|
||||
# override, not a guarantee, so "they are on the same host" is a property
|
||||
# of the auto-deployed topology rather than of the module. Without this
|
||||
# gate, a host running authelia and no collector would declare a target
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
# Two provisioning modes, ONE structure — what differs is who puts the
|
||||
# artifacts on disk, never what the artifacts are:
|
||||
#
|
||||
# - autoconfigured (`services.hyperhive.enableAllLocalDefaults`, or
|
||||
# - autoconfigured (`services.hyperhive.deploy.singleHostSwarm`, or
|
||||
# `autoConfigure` set directly): the unit below generates the root
|
||||
# here on first boot.
|
||||
# - operator-provided (multi-host): the operator installs the root cert
|
||||
|
|
@ -68,7 +68,7 @@ in
|
|||
Run the whole swarm CA on this one host: generate the swarm
|
||||
root when it is missing, and issue this hive's CA under it.
|
||||
|
||||
`services.hyperhive.enableAllLocalDefaults` turns this on as
|
||||
`services.hyperhive.deploy.singleHostSwarm` turns this on as
|
||||
part of the all-on-one-box mode. Set it here directly to run the
|
||||
CA on a host that is not otherwise all-local.
|
||||
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ in
|
|||
};
|
||||
|
||||
# `enable` moved to `services.hyperhive.deploy.swarm-controller.enable` — see
|
||||
# ./deploy.nix. `services.hyperhive.enableAllLocalDefaults` still
|
||||
# ./deploy.nix. `services.hyperhive.deploy.singleHostSwarm` still
|
||||
# asserts it, and that was never an exception to "not derived from
|
||||
# services.hyperhive.enable": that mode says "this box is the whole
|
||||
# deployment", which answers the topology question outright, where
|
||||
|
|
@ -320,7 +320,7 @@ in
|
|||
Empty means unset, which the assertion below refuses — a
|
||||
controller with no queue is not a lighter controller.
|
||||
|
||||
`enableAllLocalDefaults` fills this in with loopback, because
|
||||
`singleHostSwarm` fills this in with loopback, because
|
||||
that address is only correct when the queue is on this host:
|
||||
its container shares the host netns. That derivation lives with
|
||||
the mode rather than here, so this option describes itself
|
||||
|
|
@ -354,7 +354,7 @@ in
|
|||
The controller cannot mint its own — minting happens inside
|
||||
authelia's state directory during its first boot — so away from
|
||||
that host the operator places the secret and names it here.
|
||||
`enableAllLocalDefaults` points this at the minted file, which
|
||||
`singleHostSwarm` points this at the minted file, which
|
||||
is exactly the case where one exists locally.
|
||||
|
||||
Read by `LoadCredential`, so it needs to be readable by root at
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ in
|
|||
Leave it off wherever the queue and its clients are not the same
|
||||
operator's problem: the seeds must reach whoever runs the
|
||||
responder, and minting them here only moves that distribution
|
||||
somewhere less visible. `enableAllLocalDefaults` turns it on.
|
||||
somewhere less visible. `singleHostSwarm` turns it on.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,20 +4,20 @@
|
|||
# where they live, and asserts the per-service `enable`s that follow —
|
||||
# the same mode-not-default shape as ./local-defaults.nix, one tier down.
|
||||
#
|
||||
# Only the *optional* services derive: matrix and authelia. The forge has
|
||||
# no `enable` to assert, because it is not optional — it is the canonical
|
||||
# store for the meta flake and every agent's config repo, so it deploys
|
||||
# with hyperhive itself.
|
||||
# Only the *optional* services derive. The forge has no `enable` to
|
||||
# assert, because it is not optional — it is the canonical store for the
|
||||
# meta flake and every agent's config repo, so it deploys with hyperhive
|
||||
# itself.
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
swarmCfg = config.services.hyperhive.swarm;
|
||||
deployCfg = config.services.hyperhive.deploy;
|
||||
in
|
||||
{
|
||||
options.services.hyperhive.swarm.enableRequiredServices = lib.mkOption {
|
||||
options.services.hyperhive.deploy.allSwarmServices = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
|
|
@ -28,15 +28,16 @@ in
|
|||
and log stores — have their toggle asserted from this, so a
|
||||
swarm's service host is declared in one place.
|
||||
|
||||
Those toggles live in two namespaces and the split is deliberate:
|
||||
{option}`services.hyperhive.deploy.*` for "does THIS host run it",
|
||||
`swarm.*.enable` for the ones not yet moved. See ./deploy.nix.
|
||||
Every toggle it asserts is a {option}`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.
|
||||
|
||||
The forge is swarm-wide too but has nothing to assert: it is the
|
||||
canonical store for the meta flake and every agent's config repo,
|
||||
so it deploys with hyperhive itself and is not optional.
|
||||
|
||||
`services.hyperhive.enableAllLocalDefaults` turns this on as part
|
||||
`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.
|
||||
|
|
@ -52,49 +53,44 @@ in
|
|||
# Everything derives under `deploy.*` now, because "does THIS host run
|
||||
# it" is a per-host decision and `swarm.*` has to be identical on every
|
||||
# host. Same switch, same rule, one attribute path.
|
||||
config.services.hyperhive.deploy.matrix.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||
config.services.hyperhive.deploy.matrix.enable = lib.mkDefault deployCfg.allSwarmServices;
|
||||
|
||||
# The collector that feeds the pair above (note: no `swarm.` prefix,
|
||||
# this is ./otel.nix's existing per-hive option).
|
||||
config.services.hyperhive.otel.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||
config.services.hyperhive.otel.enable = lib.mkDefault deployCfg.allSwarmServices;
|
||||
|
||||
# The rest of the shared services, deriving from the same switch as the
|
||||
# `swarm.*` ones above. They read differently only because "does THIS
|
||||
# host run it" lives in `deploy.*` (./deploy.nix) — `swarm.*` has to be
|
||||
# identical on every host, and these are exactly the values that must
|
||||
# differ.
|
||||
# The rest of the shared services, from the same switch and for the same
|
||||
# reason.
|
||||
#
|
||||
# authelia: a swarm has one SSO provider, and this says it lives here.
|
||||
# With it off the hive is a *client* — `swarm.authelia.url` still points
|
||||
# at whoever runs it.
|
||||
config.services.hyperhive.deploy.authelia.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||
config.services.hyperhive.deploy.authelia.enable = lib.mkDefault deployCfg.allSwarmServices;
|
||||
|
||||
# The queue. Same rule: once per swarm, optional.
|
||||
config.services.hyperhive.deploy.nats.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||
config.services.hyperhive.deploy.nats.enable = lib.mkDefault deployCfg.allSwarmServices;
|
||||
|
||||
# The swarm collector that feeds the metrics pair, and the only tier
|
||||
# holding the upstream credential. ⚠️ NOT the per-hive collector below,
|
||||
# which every hive runs.
|
||||
config.services.hyperhive.deploy.swarm-otel.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||
config.services.hyperhive.deploy.swarm-otel.enable = lib.mkDefault deployCfg.allSwarmServices;
|
||||
|
||||
# The metrics pair, deriving together on purpose: a store with no UI is
|
||||
# unreadable and a UI with no store is empty, so there is no sensible
|
||||
# deployment that takes one and not the other from this switch. An
|
||||
# operator who wants exactly one still sets it directly, which
|
||||
# `mkDefault` allows.
|
||||
config.services.hyperhive.deploy.victoriametrics.enable =
|
||||
lib.mkDefault swarmCfg.enableRequiredServices;
|
||||
config.services.hyperhive.deploy.grafana.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||
config.services.hyperhive.deploy.victoriametrics.enable = lib.mkDefault deployCfg.allSwarmServices;
|
||||
config.services.hyperhive.deploy.grafana.enable = lib.mkDefault deployCfg.allSwarmServices;
|
||||
|
||||
# The log store, from the same switch for the same reason as the rest: a
|
||||
# hive that is not the service host is a *client* of it, not a second one.
|
||||
config.services.hyperhive.deploy.victorialogs.enable =
|
||||
lib.mkDefault swarmCfg.enableRequiredServices;
|
||||
config.services.hyperhive.deploy.victorialogs.enable = lib.mkDefault deployCfg.allSwarmServices;
|
||||
|
||||
# The secret store. Once per swarm and optional, so it belongs to the
|
||||
# same switch: a hive that does not run it is a *client*, reading its
|
||||
# own secrets from whoever does. `mkDefault` is what keeps the store
|
||||
# placeable on a host of its own — it can be set directly here and
|
||||
# turned off wherever this switch happens to be on.
|
||||
config.services.hyperhive.deploy.bao.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||
config.services.hyperhive.deploy.bao.enable = lib.mkDefault deployCfg.allSwarmServices;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,11 +80,11 @@ let
|
|||
# ONE condition for all three of them, deliberately.
|
||||
#
|
||||
# 🩸 They were three independent conditions first, and that was wrong in
|
||||
# a way only an eval gate finds: at the time `enableRequiredServices`
|
||||
# a way only an eval gate finds: at the time `allSwarmServices`
|
||||
# turned on matrix and authelia but NOT nats, so an ordinary all-local
|
||||
# hive resolved authelia's two coordinates and not the queue URL. Two of
|
||||
# three set is exactly what the assertion below rejects, so every
|
||||
# `enableAllLocalDefaults` hive would have stopped evaluating.
|
||||
# `singleHostSwarm` hive would have stopped evaluating.
|
||||
#
|
||||
# (The queue does derive from that switch now — ./swarm-required-services.nix
|
||||
# — so the original asymmetry is gone. The reasoning below is why the
|
||||
|
|
@ -382,7 +382,7 @@ in
|
|||
];
|
||||
};
|
||||
|
||||
# `enableRequiredServices` is declared in ./swarm-required-services.nix
|
||||
# `allSwarmServices` is declared in ./swarm-required-services.nix
|
||||
# together with the per-service `enable`s it asserts — it is a
|
||||
# deployment-shape switch rather than swarm bookkeeping, so it lives
|
||||
# with its consequences instead of here.
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ let
|
|||
];
|
||||
}).config;
|
||||
|
||||
allLocal = hive { enableAllLocalDefaults = true; };
|
||||
allLocal = hive { deploy.singleHostSwarm = true; };
|
||||
bare = hive { };
|
||||
withCi = hive { deploy.forgejo.ci.enable = true; };
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue