Watch
0
0
Fork
You've already forked hyperhive
0

nix: comments state current behaviour, not history

Rewrite comments and option descriptions under nix/ that narrate how the
code got here ("used to", "new name", "sat at the TOP", "no longer",
renamed/moved narration, attributions) to say what the code does now and
why. Comments and description strings only; no logic changes.

Files in open PR #4970's diff are left alone. Refs #3902
This commit is contained in:
atlas 2026-10-05 02:34:39 +02:00
commit 1c90619fbb
45 changed files with 331 additions and 411 deletions

View file

@ -79,10 +79,10 @@ in
#
# Both spellings, for the same reason ../host-modules/deploy.nix lists both
# of `swarm|deploy.matrix.registrationTokenFile`: an existing agent.nix may
# carry either the pre-rename `hyperhive.*` path or the current one, and only
# the one it actually carries will fire. The rename shim that used to bridge
# them is gone from ./renamed-options.nix — a rename pointing at an
# undeclared option breaks evaluation for everyone, removed or not.
# carry either the `hyperhive.*` path or the `services.hyperhive.agent.*`
# one, and only the one it actually carries will fire. Neither is an entry
# in ./renamed-options.nix — a rename pointing at an undeclared option
# breaks evaluation for everyone, removed or not.
(lib.mkRemovedOptionModule [ "hyperhive" "matrix" "enable" ] matrixEnableRemoved)
(lib.mkRemovedOptionModule [ "services" "hyperhive" "agent" "matrix" "enable" ] matrixEnableRemoved)
];

View file

@ -10,8 +10,8 @@
let
userName = config.services.hyperhive.agent.user.name;
# The token the agent fetched from the swarm secret store
# (./forge-token.nix), then the state-dir file the hive used to write,
# which is still the only copy for an agent without a store identity.
# (./forge-token.nix), then the state-dir file the hive writes, which is
# the only copy for an agent without a store identity.
# Both are PATHS; each reader below takes the first that holds a token.
fetchedTokenFile = config.services.hyperhive.agent.forge.tokenFile;
stateTokenFile = "/agents/${userName}/state/forge-token";

View file

@ -37,7 +37,7 @@ let
# per-agent "does this agent have a homeserver to reach" fact. So an agent the
# hive handed no homeserver URL, whose operator declared no external account
# either, has an empty set here and gets none of the units — the case the
# deleted `matrix.enable = false` used to express.
# "matrix off" case.
#
# No cycle: `matrixAccounts`'s own definition reads `matrix.url`, never this
# binding, so the `mkIf`s below may read the merged option value freely.
@ -75,9 +75,9 @@ in
then talks to the wrong machine. An absent integration, never a
misdirected one.
`null` is also this agent's **matrix off switch**, and the
replacement for the `services.hyperhive.agent.matrix.enable`
boolean that used to exist: the hive-internal `main` account in
`null` is also this agent's **matrix off switch** — there is no
separate `services.hyperhive.agent.matrix.enable` boolean: the
hive-internal `main` account in
`services.hyperhive.agent.matrixAccounts` is declared from this
URL, so `null` leaves that set empty and the whole integration —
daemon unit, path watcher, injected MCP entry — is not generated
@ -214,12 +214,11 @@ in
config = {
assertions = [
# The "extras require `matrix.enable`" assertion that used to head this
# list is gone with the option: a non-empty account set is now what
# enables matrix, so the condition it checked has become the definition
# of the thing it was checking. An operator declaring only an external
# account, with no hive homeserver, is a config this module now renders
# rather than rejects — matrix on, no `main`.
# There is no "extras require `matrix.enable`" assertion: a non-empty
# account set is what enables matrix, so that condition is the
# definition of the thing it would check. An operator declaring only an
# external account, with no hive homeserver, gets a rendered config —
# matrix on, no `main`.
#
# `main` is not a forbidden key --- this module declares it
# itself (see the `matrixAccounts.main` definition below), so the

View file

@ -1,10 +1,9 @@
# Deprecation shims for the agent tier's old option namespace.
# Deprecation shims for the agent tier's top-level `hyperhive.*` spelling.
#
# Every per-agent option used to live at the top level, `hyperhive.<name>`,
# while the host tier has always been under `services.hyperhive.*`. The agent
# tier moved to `services.hyperhive.agent.<name>`; these entries keep an
# existing `agent.nix` evaluating (with a deprecation warning) against the old
# spelling.
# Per-agent options live at `services.hyperhive.agent.<name>`, beside the host
# tier's `services.hyperhive.*`. These entries keep an `agent.nix` that still
# uses the top-level `hyperhive.<name>` spelling evaluating, with a
# deprecation warning.
#
# ⚠️ One entry per LEAF, not per namespace. A single entry for a parent path
# only covers its children when the parent is a submodule-typed option; every
@ -119,9 +118,9 @@
[ "hyperhive" "logs" "queryUrl" ]
[ "services" "hyperhive" "agent" "logs" "queryUrl" ]
)
# `matrix.enable` is deliberately absent from this list: the option it
# renamed to no longer exists, and a rename pointing at an undeclared
# option breaks evaluation for everyone. Both of its spellings are
# `matrix.enable` is deliberately absent from this list: it has no
# replacement option, and a rename pointing at an undeclared option
# breaks evaluation for everyone. Both of its spellings are
# `mkRemovedOptionModule` in ./default.nix instead.
(lib.mkRenamedOptionModule
[ "hyperhive" "matrix" "url" ]

View file

@ -239,8 +239,8 @@ in
# every hive — the name it answers to, the ports and URLs it is reached
# on, the client id it is registered under. These six are what the host
# running it decides; its two packages moved as well, further down with
# the other `*.package` moves. ⚠️ `enable` is NOT here: it was renamed
# earlier and its shim lives in ./hive-matrix.nix, so that file is the one
# the other `*.package` moves. ⚠️ `enable` is NOT here: its shim lives in
# ./hive-matrix.nix, so that file is the one
# to check before assuming this table is the whole matrix story.
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "swarm" "matrix" "openFirewall" ]
@ -255,7 +255,7 @@ in
[ "services" "hyperhive" "deploy" "matrix" "maxRequestSize" ]
)
# Both spellings of the registration token, removed rather than renamed:
# the homeserver no longer accepts a shared registration secret at all,
# the homeserver does not accept a shared registration secret at all,
# so there is no path to point a definition at. Accounts are created by
# the swarm's appservice.
(lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "matrix" "registrationTokenFile" ] ''
@ -301,28 +301,27 @@ in
[ "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.
# The switch over all of the above. `allSwarmServices` says whether THIS
# host runs every service the swarm requires; those services are
# required of the SWARM, so the name is about the swarm rather than this
# host's wiring.
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "swarm" "enableRequiredServices" ]
[ "services" "hyperhive" "deploy" "allSwarmServices" ]
)
# The mode above that one. 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.
# The mode above that one lives under `deploy`, not at the TOP of
# `services.hyperhive`: that namespace is everything about hyperhive, not
# the settings of a single hive. `singleHostSwarm` names what the mode
# asserts — the whole swarm runs on this host — instead of its mechanism.
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "enableAllLocalDefaults" ]
[ "services" "hyperhive" "deploy" "singleHostSwarm" ]
)
# The hive TLS state dir sat at the TOP of `services.hyperhive`, which is
# meant to be everything about hyperhive rather than the settings of one
# hive. `hive-controller` is hive-c0re's new name (mara, on the issue).
# The hive TLS state dir lives under `deploy.hive-controller` (the
# hive-c0re daemon's namespace), not at the TOP of `services.hyperhive`,
# which is everything about hyperhive rather than the settings of one hive.
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "tls" "stateDir" ]
[ "services" "hyperhive" "deploy" "hive-controller" "tls" "stateDir" ]

View file

@ -86,8 +86,8 @@ in
clientKeyFile = lib.mkDefault "${pkiDir}/client-key.pem";
serverCaFile = lib.mkDefault "${pkiDir}/ca.pem";
# 🩸 Readers that used to present `client.pem` above, each now pointed at
# a leaf of its own. The leaf is what bao sees, so this pairing is the
# 🩸 The readers below each present a leaf of their own rather than
# `client.pem` above. The leaf is what bao sees, so this pairing is the
# whole of what turns "one principal with the union of their grants" into
# one principal per grant — see ./swarm-bao.nix's `perHiveReaders` block
# for the grants themselves.
@ -193,11 +193,11 @@ in
[ -s ${pkiDir}/matrix-ctl.pem ] || ${signLeaf} ${pkiDir} matrix-ctl \
${lib.escapeShellArg deployCfg.bao.matrixCtlCommonName} "" clientAuth
# 🩸 The readers that used to present `client.pem` above. Each carries
# 🩸 The readers' leaves, separate from `client.pem` above. Each carries
# its own subject, which is the entire mechanism: bao matches a
# cert-auth role on the CN, so units sharing one leaf were one principal
# holding the union of their grants, and the union included every agent
# credential in the swarm.
# cert-auth role on the CN, so units sharing one leaf would be one
# principal holding the union of their grants, and the union would
# include every agent credential in the swarm.
#
# ⚠️ The first carries THIS hive's name in the subject, unlike the three
# service leaves above. Its grant names one hive's path, because a queue

View file

@ -42,9 +42,9 @@ let
# a certificate the store accepts, and that is true on the store's own host
# and on a hive three networks away for exactly the same reason.
#
# 🩸 This principal's OWN leaf, not `clientCertFile` — the hive's, which four
# units used to share. Bao matches a cert-auth role on the CN, so one leaf for
# four readers was ONE principal holding the union of four grants: read on
# 🩸 This principal's OWN leaf, not `clientCertFile` — the hive's. Bao
# matches a cert-auth role on the CN, so one leaf shared by four readers
# would be ONE principal holding the union of four grants: read on
# `swarm/agents/*` AND `swarm/hives/<hive>/*` AND `swarm/services/*`, when
# this unit reads one queue credential and nothing else. Its own leaf carries
# `<queueAgentCommonNamePrefix>-<hive>` and its role grants the single path
@ -53,11 +53,11 @@ let
baoDeploy.queueAgentClientCertFile != null && baoDeploy.queueAgentClientKeyFile != null;
# Does this host read the store at all — the hive's own leaf, which is the
# one thing a remote-store deployment has always had to place by hand. Only
# used to decide whether a missing per-principal leaf is a mistake or a
# deployment that has no store: a host holding neither is the supported
# no-store shape, and one holding this pair but not the pair above stopped
# short of naming this reader's own.
# one thing a remote-store deployment has to place by hand. Only used to
# decide whether a missing per-principal leaf is a mistake or a deployment
# that has no store: a host holding neither is the supported no-store
# shape, and one holding this pair but not the pair above reads the store
# without a reader identity of its own.
hiveReaderIdentity = baoDeploy.clientCertFile != null && baoDeploy.clientKeyFile != null;
credentialDir = toString deployCfg.hive-controller.queue.agentCredentialDir;

View file

@ -115,17 +115,14 @@ in
HYPERHIVE_OTEL_EXTRA_RESOURCE_ATTRIBUTES = otel.extraResourceAttributes;
}
# HYPERHIVE_OTEL_HEADERS_CREDENTIAL is deliberately NOT emitted, and
# its absence is the security half of this design: it was the variable
# that put the upstream token into an agent's own settings.json. The
# delivery path it drove — an nspawn credential forwarded by
# host_config.rs, then written to an agent-readable file by
# claude-settings.nix's `hive-otel-header` oneshot — no longer exists
# anywhere; it was removed along with this variable's last consumer.
# its absence is the security half of this design: that variable would
# put the upstream token into an agent's own settings.json. Nothing
# delivers the token into the container — no nspawn credential, no
# agent-readable header file.
#
# Kept as a comment rather than deleted because the useful part is the
# RULE, not the history: the collector holding the credential achieves
# nothing while anything else hands out a copy, so there is exactly one
# holder and it is on the host.
# The rule: the collector holding the credential achieves nothing while
# anything else hands out a copy, so there is exactly one holder and it
# is on the host.
// lib.optionalAttrs (otel.metricIntervalMs != null) {
HYPERHIVE_OTEL_METRIC_INTERVAL_MS = toString otel.metricIntervalMs;
}

View file

@ -207,11 +207,8 @@ in
# `caTrust.containerOrdering` orders this unit after `hive-tls-ca.service`
# in self-signed mode (see the hive-ca-trust helper). Runner registration
# is no longer on the boot-critical path — hive-c0re owns it out of band —
# so the container boots immediately and needs no start-timeout bump. The
# former `TimeoutStartSec = mkForce "180s"` band-aid (which papered over a
# boot-path forge + core-token round-trip that could trip the nspawn start
# timeout into a ~60s restart loop) is gone with that move.
# is not on the boot-critical path — hive-c0re owns it out of band — so
# the container boots immediately and needs no start-timeout bump.
systemd.services."container@hive-ci" = caTrust.containerOrdering;
containers.hive-ci = {
@ -415,7 +412,7 @@ in
# runner stays down (Restart=on-failure retries) until c0re
# registers it, rather than blocking the container's start.
#
# No nix-daemon wait anymore: builds route through the HOST daemon
# No nix-daemon wait: builds route through the HOST daemon
# (bound socket above), which is up before the container — nix's
# own connect retries cover any brief window. `mkBefore` runs this
# ahead of any upstream pre-steps.

View file

@ -142,11 +142,6 @@ in
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.
**Breaking change**: this used to default to `true`. If you
relied on the old default for external reach, add
`services.hyperhive.deploy.forgejo.openFirewall = true;` to your
host config before rebuilding.
'';
};
@ -783,7 +778,7 @@ in
Group = "forgejo";
SyslogIdentifier = "forgejo-sso-source";
};
# `FORGEJO_CUSTOM` (not `GITEA_CUSTOM` — forgejo renamed it)
# `FORGEJO_CUSTOM` (the forgejo-prefixed name, not `GITEA_CUSTOM`)
# is how the CLI finds the app.ini upstream's module wrote.
#
# This unit is also a trust-bundle consumer (declared in the
@ -930,29 +925,25 @@ in
# re-mint instead of being silently masked by a stamp that
# outlived what it claims exists.
if [ ! -s "$token_path" ]; then
# `write:admin` added for `swarm-controller::forge::Client::
# ensure_agent_user` (the `CreateForgeUser` jobq node) —
# Forgejo's `admin_create_user` HTTP endpoint refused every
# call with "token does not have at least one of required
# scope(s): [write:admin]" without it, an already-deployed
# swarm hitting this the moment that node shipped. A host
# whose token was minted before this scope was added won't
# pick it up automatically — the `[ ! -s "$token_path" ]`
# guard above only mints when the file is absent, by design
# (see its own comment) — so an existing deployment needs
# its token file deleted to force a re-mint with the new
# scope.
# `write:admin` is required by `swarm-controller::forge::Client::
# ensure_agent_user` (the `CreateForgeUser` jobq node):
# Forgejo's `admin_create_user` HTTP endpoint refuses a
# token without it ("token does not have at least one of
# required scope(s): [write:admin]"). A host whose token was
# minted without this scope keeps it — the
# `[ ! -s "$token_path" ]` guard above only mints when the
# file is absent, by design (see its own comment) — so such a
# deployment needs its token file deleted to force a re-mint
# with the full scope.
#
# Token name carries a timestamp suffix rather than the
# fixed `swarm-controller-boot` this used to be — a real
# incident, not a hypothetical: deleting the token *file*
# (the remediation above) doesn't delete the token Forgejo
# already has under that name, so re-running this unit hit
# "Command error: access token name has been used already"
# and failed outright. Same fix `hive-c0re::forge::users::
# mint_token` already uses for its own agent tokens, for
# the identical reason — a monotonic suffix means a re-mint
# can never collide with whatever this account already has.
# Token name carries a timestamp suffix rather than a fixed
# name: deleting the token *file* (the remediation above)
# doesn't delete the token Forgejo already has under that
# name, so re-running this unit would fail with "Command
# error: access token name has been used already". Same
# approach `hive-c0re::forge::users::mint_token` uses for its
# own agent tokens — a monotonic suffix means a re-mint can
# never collide with whatever this account already has.
out=$(forgejo admin user generate-access-token \
--username ${lib.escapeShellArg swarmControllerForgeUser} \
--token-name "swarm-controller-boot-$(date +%s)" \

View file

@ -30,9 +30,10 @@ let
effectiveRootUrl = if cfg.rootUrl != null then cfg.rootUrl else defaultRootUrl;
in
{
# Forge moved under `swarm` when the swarm-global services were
# consolidated. One rename for the namespace: the subtree comes with it,
# so existing hives keep evaluating and get one warning naming both paths.
# Forge lives under `swarm`, beside the other swarm-global services. One
# rename for the top-level `services.hyperhive.forge` namespace: the
# subtree comes with it, so existing hives keep evaluating and get one
# warning naming both paths.
imports = [
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "forge" ]

View file

@ -55,10 +55,9 @@ let
# `cfg.useSelfSigned` (options.nix) is the derived single source of truth.
useSelfSigned = cfg.useSelfSigned;
# nginx's own state dir. Kept at the historical `/var/lib/hive-gateway`
# path rather than renamed with the move: it holds the imported leaf
# across reboots, and renaming it would strand every existing hive's
# certs for no gain.
# nginx's own state dir, fixed at `/var/lib/hive-gateway` independent of
# this module's own path: it holds the imported leaf across reboots, and
# a different path would strand every existing hive's certs.
tlsDir = "/var/lib/hive-gateway/tls";
# TLS cert + key paths.
# - self-signed (default): the hive leaf the store issues (the
@ -207,14 +206,12 @@ in
# before c0re has run, and pin owner + mode rather than leaving it
# to whoever creates the path first.
#
# ⚠️ There is deliberately NO rule for /var/lib/hyperhive here. One
# used to declare it `0755 root root` and could never win:
# ⚠️ There is deliberately NO rule for /var/lib/hyperhive here.
# `hive-c0re.service` sets `StateDirectory = "hyperhive"` with
# `StateDirectoryMode = "0750"`, which systemd re-applies on every
# start. Two mechanisms owning one path, and the loser still read as
# a guarantee — it is why the resulting outage was first misdiagnosed
# as someone having changed the mode. c0re's own unit owns that dir;
# this module no longer has an opinion about it.
# start, so a tmpfiles rule for the same path could never win: two
# mechanisms owning one path, the loser still reading as a guarantee.
# c0re's own unit owns that dir; this module has no opinion about it.
systemd.tmpfiles.rules = [
# The gateway's own config dir — NOT under /var/lib/hyperhive. c0re
# writes here, nginx reads here, and neither needs any access to the
@ -393,23 +390,15 @@ in
# ⚠️ NO `SupplementaryGroups = [ "hive-core" ]` on nginx, and its
# absence is load-bearing rather than an omission.
#
# It used to be here, to let nginx traverse `/var/lib/hyperhive` and
# reach the config fragments that lived inside: `hive-c0re.service`
# declares `StateDirectory = "hyperhive"` with `StateDirectoryMode =
# "0750"` owned by `hive-core`, and systemd re-applies that on every
# c0re start — beating this module's own tmpfiles rule for the same
# path. Without the group, nginx failed its config test and never
# started (`nginx: [emerg] open() ".../agents.conf" failed (13:
# Permission denied)`), taking the gateway and every hive domain
# behind it down.
#
# The group fixed the symptom and paid for it: it also gave nginx
# read access to everything ELSE group-readable under that dir,
# including the broker sqlite — i.e. every message between every
# agent, reachable by the process whose entire job is parsing
# untrusted network input. Moving the fragments to the gateway's own
# dir removes the need and the exposure together. Re-adding this line
# would restore both.
# `hive-c0re.service` declares `StateDirectory = "hyperhive"` with
# `StateDirectoryMode = "0750"` owned by `hive-core`, and systemd
# re-applies that on every c0re start. The group would let nginx
# traverse that dir, but it also gives nginx read access to everything
# ELSE group-readable under it, including the broker sqlite — i.e.
# every message between every agent, reachable by the process whose
# entire job is parsing untrusted network input. The config fragments
# nginx reads live in the gateway's own dir instead, so nginx needs no
# access to c0re's tree. Adding this line would reopen that exposure.
networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [
@ -424,12 +413,11 @@ in
# every name a service module contributed. See `docs/networking/gateway.md`
# ("Local dev").
#
# This used to restate the per-service list a THIRD time (after the
# vhosts and the dnsmasq records), with its own copy of each
# service's guard. It is the same question — "which names does this
# host answer for" — so it reads the same answer; a service added
# later lands here with no edit, and cannot land here with a
# different condition than it used for DNS.
# This does not restate the per-service list (the vhosts and the
# dnsmasq records already carry it). It is the same question —
# "which names does this host answer for" — so it reads the same
# answer; a service added later lands here with no edit, and cannot
# land here with a different condition than it used for DNS.
networking.hosts = lib.mkIf cfg.localHostsEntry {
"127.0.0.1" = lib.unique ([ hyperhiveDomain ] ++ cfg.localNames);
};

View file

@ -82,10 +82,6 @@ in
nginx vhost. Leave off when running behind another reverse
proxy (e.g. caddy / traefik on the host) that handles TLS
termination + forwards to `port`.
**Note**: this used to default to `true`. Add
`services.hyperhive.gateway.openFirewall = true;` to your host
config if external reach stopped working after a recent upgrade.
'';
};

View file

@ -187,22 +187,19 @@ let
# Swagger UI: nginx hosts the FULL themed dist (`swaggerUiTheme` —
# vendored Swagger UI + our overlay, see nix/packages/swagger-ui-
# dist.nix + swagger-ui-theme.nix) straight from the store, with NO
# fallback to hive-c0re at all — per the operator's shape: "core
# should not need the swagger ui at all if it is hosted in gateway"
# / "core only hosts the json". Only `/api/openapi.json`
# (the live-generated spec `index.html` fetches; not under this
# prefix) still proxies to c0re via "/api/" below — that's the one
# thing that has to stay dynamic.
# fallback to hive-c0re at all: core hosts only the JSON. Only
# `/api/openapi.json` (the live-generated spec `index.html` fetches;
# not under this prefix) proxies to c0re via "/api/" below — that's
# the one thing that has to stay dynamic.
#
# Prefix location, not exact-match: wins over "/api/" on plain
# prefix length (no ordering/`=` needed), and now needs to cover
# every file in the tree (bundle.js, maps, favicons, …), not just
# our 2 override files — hive-c0re no longer serves any of this as
# a fallback once its own `utoipa-swagger-ui` mount is removed.
# `= /api/docs` (no trailing slash) issues the same redirect
# `utoipa-swagger-ui`'s router used to: that mount is going away
# too, so nginx has to own it now, or the H0M3 hub's own `/api/docs`
# link (no trailing slash) would 404 once hive-c0re drops the route.
# prefix length (no ordering/`=` needed), and covers every file in
# the tree (bundle.js, maps, favicons, …), not just our 2 override
# files — hive-c0re serves none of this as a fallback.
# `= /api/docs` (no trailing slash) redirects to `/api/docs/`: nginx
# owns that redirect because hive-c0re has no route for it, and the
# H0M3 hub's own `/api/docs` link (no trailing slash) would 404
# without it.
swaggerUiLocations = {
"= /api/docs" = {
extraConfig = ''

View file

@ -153,12 +153,11 @@ let
# to host it — otherwise moving the container between hives would look
# like a different homeserver.
#
# ⚠️ Changing this default is a BREAKING change in a way that moving
# `gatewayHost` was not: `serverName` is baked irrevocably into every
# user and room id, so a deployment that rebuilds onto a new one is a
# *different homeserver*, not a renamed one. Existing hives pin the old
# value explicitly (see the option's description); the default is what
# a fresh swarm gets.
# ⚠️ Changing this default is breaking: `serverName` is baked
# irrevocably into every user and room id, so a deployment that
# rebuilds onto a new one is a *different homeserver*. Existing hives
# pin their value explicitly (see the option's description); the
# default is what a fresh swarm gets.
#
# Total on a null swarm domain, deliberately: the required-domain
# assertion in hive-network.nix is what should fire, not a coercion
@ -251,9 +250,10 @@ in
# settings: docs/integrations/matrix.md. Vhost map + discovery flow + tuning
# knobs: docs/networking/gateway.md.
# Matrix moved under `swarm` when the swarm-global services were
# consolidated. One rename for the namespace: the subtree comes with it,
# so existing hives keep evaluating and get one warning naming both paths.
# Matrix lives under `swarm`, beside the other swarm-global services. One
# rename for the top-level `services.hyperhive.matrix` namespace: the
# subtree comes with it, so existing hives keep evaluating and get one
# warning naming both paths.
imports = [
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "matrix" ]
@ -311,11 +311,6 @@ in
the homeserver to other hives or when an external matrix
client needs to reach the client-server API directly.
**Breaking change**: this used to default to `true`. If you
relied on the old default for external reach, add
`services.hyperhive.deploy.matrix.openFirewall = true;` to your host
config before rebuilding.
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

View file

@ -130,9 +130,9 @@ let
# leaf to hold, and its absence there is the correct state rather
# than a stale one — its own vhosts are covered by the hive leaf
# above. Anywhere else it is expected: the leaf comes from the
# secret store's `pki` mount now, not from a sub-CA that exists on
# one host in the swarm, so "this host cannot issue it" is no longer
# one of the answers.
# secret store's `pki` mount, reachable from every host rather than
# from a sub-CA on one host in the swarm, so "this host cannot issue
# it" is not one of the answers.
want_svc=${if localServiceDomains == [ ] then "0" else "1"}
# Expiry is not the only way a leaf goes wrong. One signed when the
@ -346,17 +346,14 @@ in
};
config = lib.mkIf active {
# 🚫 The "these service names are outside this hive's domain and this
# host cannot sign for them" warning is GONE, and its absence is the
# deliverable rather than a tidy-up. It fired on
# `!swarm.ca.autoConfigure` — i.e. "this host does not hold the swarm
# root key" — which was the whole reason a hive could end up serving
# its own leaf on a swarm-service name. The services leaf now comes
# from the secret store's `pki` mount, which every hive reaches over
# the network with its own identity, so holding the root key stopped
# being the thing that decides. Left in place it would warn, on every
# rebuild of every hive that is not the CA host, about a fallback
# that no longer happens.
# 🚫 There is deliberately NO warning that these service names are
# outside this hive's domain and this host cannot sign for them. The
# services leaf comes from the secret store's `pki` mount, which every
# hive reaches over the network with its own identity, so holding the
# swarm root key does not decide whether a hive can serve a
# swarm-service name. Such a warning would fire on every rebuild of
# every hive that is not the CA host, about a fallback that does not
# happen.
# The state dir and the trust bundle. Never waits on the store: the
# store's container is ordered after this unit, which writes the

View file

@ -103,8 +103,8 @@ in
# Where the swarm lives. Declared beside the hive's own identity
# because it is what that identity is derived FROM — every hive in a
# swarm is a sub-domain of it. Unlike the renamed options nearby, this
# is genuinely new: nothing moved here, so there is no alias.
# swarm is a sub-domain of it. No alias: this option has no earlier
# spelling.
options.services.hyperhive.swarm.domain = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
@ -145,7 +145,7 @@ in
(`services.hyperhive.deploy.hive-controller.enable`,
`deploy.bao.enable`, `deploy.matrix.enable`). Distinct from
`services.hyperhive.domain` (the machine-addressable DNS name)
but no longer merely cosmetic: a hive occupies
and not merely cosmetic: a hive occupies
`<hiveName>.<swarm.domain>`, so this is the label the hive is
*addressed* by as well as the one it is called. Exposed to
agents as `HYPERHIVE_HIVE_NAME`; surfaced in the dashboard

View file

@ -60,9 +60,8 @@ in
# rather than the file.
#
# ⛔ **Do not hand this path to a consumer that reads only ONE
# certificate from it.** This comment used to offer an OIDC verifier's
# `issuer_ca_path` as the motivating example; that is exactly what took
# the swarm collector down for forty minutes once. The bundle is
# certificate from it** — an OIDC verifier's `issuer_ca_path` is
# exactly such a reader, and takes the swarm collector down. The bundle is
# `system CAs ++ hive anchors`, so the anchor is ~123rd, and a
# first-certificate-only reader gets whichever public CA sorts first and
# can verify nothing of ours — with a full, valid, 125-certificate file

View file

@ -68,7 +68,7 @@ in
⚠️ The collector is therefore in the path of all telemetry. It runs
on the same host as the agents and restarts on failure, and
telemetry is not the control plane, so degraded telemetry is not
degraded operation — but the export no longer survives independently
degraded operation — but the export does not survive independently
of anything host-side
'';
@ -239,7 +239,7 @@ in
onward, which is one hop for the whole hive rather than one per
target.
No longer empty on a default hive: this collector's own endpoint
Not empty on a default hive: this collector's own endpoint
is always in here, so the scrape receiver is emitted everywhere.
The `!= { }` guards around it stay meaningful — the set can still
be forced empty, and a `prometheus` receiver with nothing to

View file

@ -132,10 +132,10 @@ in
tracked as a follow-up rather than papered over.
On by default: a swarm's hives have identities, and that is a
fact about the swarm rather than about any one host. It used to
default to whether the queue ran on *this* machine, which made
the answer differ between two hosts of one swarm — set it false
for a swarm whose hives authenticate to nothing.
fact about the swarm rather than about any one host. It does not
depend on whether the queue runs on *this* machine, so the answer
is the same on every host of one swarm — set it false for a swarm
whose hives authenticate to nothing.
The clients are inert until something authenticates with them:
each is a client id and a secret sitting on this host. What

Some files were not shown because too many files have changed in this diff Show more