deploy: move the queue toggle
Same shape as the others. Three of the eight references were prose rather than code: two assertion messages naming the option to an operator, and a `defaultText` in the authelia module, whose `oidc.hiveIdentities` derives from whether the queue runs here. Also corrects a comment in swarm.nix that this commit's own hunk sits directly beneath. It said `enableRequiredServices` turns on matrix and authelia "but NOT nats (nats has no mode that enables it)", which stopped being true when the queue was added to that switch — before this change, not by it. The reasoning it introduces is still right and still worth keeping; only the premise had expired.
This commit is contained in:
parent
37ca7676d6
commit
64e8c62f18
7 changed files with 45 additions and 30 deletions
|
|
@ -57,6 +57,10 @@ in
|
||||||
[ "services" "hyperhive" "swarm" "authelia" "enable" ]
|
[ "services" "hyperhive" "swarm" "authelia" "enable" ]
|
||||||
[ "services" "hyperhive" "deploy" "authelia" ]
|
[ "services" "hyperhive" "deploy" "authelia" ]
|
||||||
)
|
)
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "hyperhive" "swarm" "nats" "enable" ]
|
||||||
|
[ "services" "hyperhive" "deploy" "nats" ]
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
options.services.hyperhive.deploy = {
|
options.services.hyperhive.deploy = {
|
||||||
|
|
@ -119,6 +123,19 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nats = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Run the swarm's message queue in a `swarm-nats` container on this
|
||||||
|
host. A swarm has one queue, so this belongs on the same host as
|
||||||
|
the rest of the shared services.
|
||||||
|
|
||||||
|
Off by default, and off means *absent*: no container is created
|
||||||
|
and nothing else in the evaluated config changes.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
controller = lib.mkOption {
|
controller = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ in
|
||||||
# ran its first boot on — so they belong to the mode that asserts this
|
# ran its first boot on — so they belong to the mode that asserts this
|
||||||
# box is the whole deployment, not to the options' own `default`.
|
# box is the whole deployment, not to the options' own `default`.
|
||||||
#
|
#
|
||||||
# Deriving them from `swarm.nats.enable` / `deploy.authelia`
|
# Deriving them from `deploy.nats` / `deploy.authelia`
|
||||||
# inside those defaults is the mixing this file exists to prevent: the
|
# inside those defaults is the mixing this file exists to prevent: the
|
||||||
# option would be describing a deployment shape instead of describing
|
# option would be describing a deployment shape instead of describing
|
||||||
# itself, and "what does all-local turn on?" would stop having one
|
# itself, and "what does all-local turn on?" would stop having one
|
||||||
|
|
|
||||||
|
|
@ -467,8 +467,8 @@ in
|
||||||
|
|
||||||
oidc.hiveIdentities = lib.mkOption {
|
oidc.hiveIdentities = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = hyperhiveCfg.swarm.nats.enable;
|
default = deployCfg.nats;
|
||||||
defaultText = lib.literalExpression "services.hyperhive.swarm.nats.enable";
|
defaultText = lib.literalExpression "services.hyperhive.deploy.nats";
|
||||||
description = ''
|
description = ''
|
||||||
Mint one machine client per hive in
|
Mint one machine client per hive in
|
||||||
{option}`services.hyperhive.swarm.hives`, so each hive can
|
{option}`services.hyperhive.swarm.hives`, so each hive can
|
||||||
|
|
|
||||||
|
|
@ -539,7 +539,7 @@ in
|
||||||
services.hyperhive.swarm.controller.queue.natsUrl is unset.
|
services.hyperhive.swarm.controller.queue.natsUrl is unset.
|
||||||
|
|
||||||
It defaults to loopback only when this host also runs the queue
|
It defaults to loopback only when this host also runs the queue
|
||||||
(`services.hyperhive.swarm.nats.enable`). A controller on its
|
(`services.hyperhive.deploy.nats`). A controller on its
|
||||||
own host has to be told where the queue is.
|
own host has to be told where the queue is.
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ let
|
||||||
hostPath = name: "${secretDir}/${name}";
|
hostPath = name: "${secretDir}/${name}";
|
||||||
|
|
||||||
# The responder needs all three credentials. Gating on them rather than
|
# The responder needs all three credentials. Gating on them rather than
|
||||||
# on `cfg.enable` keeps a half-configured hive at "queue up, denying
|
# on `deployCfg.nats` keeps a half-configured hive at "queue up, denying
|
||||||
# everyone" instead of "unit crash-looping on a missing file".
|
# everyone" instead of "unit crash-looping on a missing file".
|
||||||
#
|
#
|
||||||
# In auto mode the seeds are minted on this host before the container
|
# In auto mode the seeds are minted on this host before the container
|
||||||
|
|
@ -210,18 +210,9 @@ in
|
||||||
# per-service vhost pattern do not apply.
|
# per-service vhost pattern do not apply.
|
||||||
|
|
||||||
options.services.hyperhive.swarm.nats = {
|
options.services.hyperhive.swarm.nats = {
|
||||||
enable = lib.mkOption {
|
# `enable` moved to `services.hyperhive.deploy.nats` — see
|
||||||
type = lib.types.bool;
|
# ./deploy.nix. What stays here is what the queue IS: its domain,
|
||||||
default = false;
|
# ports, accounts and callout wiring.
|
||||||
description = ''
|
|
||||||
Run the swarm's message queue in a `swarm-nats` container on this
|
|
||||||
host. A swarm has one queue, so this belongs on the same host as
|
|
||||||
the rest of the shared services.
|
|
||||||
|
|
||||||
Off by default, and off means *absent*: no container is created
|
|
||||||
and nothing else in the evaluated config changes.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# ⚠️ Deliberately NO `package` option, unlike this module's siblings.
|
# ⚠️ Deliberately NO `package` option, unlike this module's siblings.
|
||||||
# `services.nats` upstream does not expose one — it resolves
|
# `services.nats` upstream does not expose one — it resolves
|
||||||
|
|
@ -408,7 +399,7 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf deployCfg.nats {
|
||||||
# The responder as well as the server: a denial reaches the client as a
|
# The responder as well as the server: a denial reaches the client as a
|
||||||
# timeout, so the server's own log is the only place it is an error.
|
# timeout, so the server's own log is the only place it is an error.
|
||||||
services.hyperhive.swarm.otel.journaldUnits = [
|
services.hyperhive.swarm.otel.journaldUnits = [
|
||||||
|
|
@ -423,7 +414,7 @@ in
|
||||||
# several layers from "the operator never set the issuer".
|
# several layers from "the operator never set the issuer".
|
||||||
assertion = cfg.autoGenerateCallout || cfg.calloutIssuerPublicKey != "";
|
assertion = cfg.autoGenerateCallout || cfg.calloutIssuerPublicKey != "";
|
||||||
message = ''
|
message = ''
|
||||||
services.hyperhive.swarm.nats.enable requires
|
services.hyperhive.deploy.nats requires
|
||||||
nats.calloutIssuerPublicKey — the public half of the account
|
nats.calloutIssuerPublicKey — the public half of the account
|
||||||
nkey that signs user JWTs for this queue.
|
nkey that signs user JWTs for this queue.
|
||||||
|
|
||||||
|
|
@ -440,7 +431,7 @@ in
|
||||||
# somebody connects.
|
# somebody connects.
|
||||||
assertion = cfg.autoGenerateCallout || cfg.calloutUserPublicKey != "";
|
assertion = cfg.autoGenerateCallout || cfg.calloutUserPublicKey != "";
|
||||||
message = ''
|
message = ''
|
||||||
services.hyperhive.swarm.nats.enable requires
|
services.hyperhive.deploy.nats requires
|
||||||
nats.calloutUserPublicKey — the public half of the user nkey
|
nats.calloutUserPublicKey — the public half of the user nkey
|
||||||
the auth-callout responder authenticates as.
|
the auth-callout responder authenticates as.
|
||||||
|
|
||||||
|
|
@ -485,7 +476,7 @@ in
|
||||||
{
|
{
|
||||||
assertion = autheliaUrl != null;
|
assertion = autheliaUrl != null;
|
||||||
message = ''
|
message = ''
|
||||||
services.hyperhive.swarm.nats.enable requires
|
services.hyperhive.deploy.nats requires
|
||||||
services.hyperhive.swarm.authelia.url — the queue authenticates
|
services.hyperhive.swarm.authelia.url — the queue authenticates
|
||||||
clients by validating tokens that authelia issued.
|
clients by validating tokens that authelia issued.
|
||||||
|
|
||||||
|
|
@ -684,7 +675,7 @@ in
|
||||||
# door nobody can open, which is the deliberate interim state.
|
# door nobody can open, which is the deliberate interim state.
|
||||||
#
|
#
|
||||||
# ⚠️ It is gated on the seeds being configured rather than on
|
# ⚠️ It is gated on the seeds being configured rather than on
|
||||||
# `cfg.enable`, so a half-configured hive gets a running,
|
# `deployCfg.nats`, so a half-configured hive gets a running,
|
||||||
# refusing queue instead of a unit that crash-loops on a
|
# refusing queue instead of a unit that crash-loops on a
|
||||||
# missing file. A queue that denies everyone is a legible
|
# missing file. A queue that denies everyone is a legible
|
||||||
# failure; a restart loop is not.
|
# failure; a restart loop is not.
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ in
|
||||||
# derives `nats.autoGenerateCallout` from the all-local mode, so that
|
# derives `nats.autoGenerateCallout` from the all-local mode, so that
|
||||||
# mode was minting the queue's callout nkeys and then never starting
|
# mode was minting the queue's callout nkeys and then never starting
|
||||||
# the queue they authenticate against.
|
# the queue they authenticate against.
|
||||||
nats.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
|
||||||
|
|
||||||
# The metrics pair and the log store used to derive here too. They now
|
# The metrics pair and the log store used to derive here too. They now
|
||||||
# live under `deploy.*` (below, and ./deploy.nix) because "does THIS
|
# live under `deploy.*` (below, and ./deploy.nix) because "does THIS
|
||||||
|
|
@ -89,6 +88,9 @@ in
|
||||||
# at whoever runs it.
|
# at whoever runs it.
|
||||||
config.services.hyperhive.deploy.authelia = lib.mkDefault swarmCfg.enableRequiredServices;
|
config.services.hyperhive.deploy.authelia = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||||
|
|
||||||
|
# The queue. Same rule: once per swarm, optional.
|
||||||
|
config.services.hyperhive.deploy.nats = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||||
|
|
||||||
# The metrics pair, deriving together on purpose: a store with no UI is
|
# 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
|
# 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
|
# deployment that takes one and not the other from this switch. An
|
||||||
|
|
|
||||||
|
|
@ -80,18 +80,23 @@ let
|
||||||
# ONE condition for all three of them, deliberately.
|
# ONE condition for all three of them, deliberately.
|
||||||
#
|
#
|
||||||
# 🩸 They were three independent conditions first, and that was wrong in
|
# 🩸 They were three independent conditions first, and that was wrong in
|
||||||
# a way only an eval gate finds: `enableRequiredServices` turns on
|
# a way only an eval gate finds: at the time `enableRequiredServices`
|
||||||
# matrix and authelia but NOT nats (nats has no mode that enables it —
|
# turned on matrix and authelia but NOT nats, so an ordinary all-local
|
||||||
# see the auto-deploy question on the swarm-queue issue), so an ordinary
|
# hive resolved authelia's two coordinates and not the queue URL. Two of
|
||||||
# all-local hive resolved authelia's two coordinates and not the queue
|
# three set is exactly what the assertion below rejects, so every
|
||||||
# URL. Two of three set is exactly what the assertion below rejects, so
|
# `enableAllLocalDefaults` hive would have stopped evaluating.
|
||||||
# every `enableAllLocalDefaults` 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
|
||||||
|
# single predicate stays anyway: it makes the partial state
|
||||||
|
# unrepresentable rather than merely detected, which does not depend on
|
||||||
|
# which services happen to derive together this month.)
|
||||||
#
|
#
|
||||||
# Deriving all three from one predicate makes the partial state
|
# Deriving all three from one predicate makes the partial state
|
||||||
# unrepresentable rather than merely detected: a default set is all or
|
# unrepresentable rather than merely detected: a default set is all or
|
||||||
# nothing, and the assertion is then only ever about what an operator
|
# nothing, and the assertion is then only ever about what an operator
|
||||||
# typed.
|
# typed.
|
||||||
queueLocal = swarmCfg.nats.enable && deployCfg.authelia && cfg.hiveName != null;
|
queueLocal = deployCfg.nats && deployCfg.authelia && cfg.hiveName != null;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.hyperhive.swarm.hives = lib.mkOption {
|
options.services.hyperhive.swarm.hives = lib.mkOption {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue