Watch
0
0
Fork
You've already forked hyperhive
0

render the matrix appservice registration from the store onto tmpfs

swarm-matrix-ctl appservice render now reads the registration's tokens
from the store and renders swarm.yaml under /run/swarm-matrix-appservice,
which tuwunel loads through LoadCredential. It mints a pair only when the
store answers and holds none; a host that has the old files stores their
pair once instead. A store that does not answer fails the unit and keeps
tuwunel down; sync starts it once the store answers.

Refs #4998 (item 3)
This commit is contained in:
atlas 2026-10-30 05:47:39 +01:00 • committed by mara
commit 3a4b0ffabf

View file

@ -258,13 +258,15 @@ let
creds =
baoWithMatrix.containers.hive-matrix.config.systemd.services.tuwunel.serviceConfig.LoadCredential;
in
lib.elem "swarm-appservice.yaml:/var/lib/swarm-matrix-appservice/swarm.yaml" creds
lib.elem "swarm-appservice.yaml:/run/swarm-matrix-appservice/swarm.yaml" creds
&& lib.length (lib.filter (c: lib.hasInfix ".yaml:" c) creds) == 1;
}
{
# A missing `LoadCredential` source fails tuwunel, so the render has to
# have run first — and it is local only, so it cannot fail on a store.
name = "the swarm registration is rendered before tuwunel and required by it, without the store";
# have run first. It fetches from the store, so it carries the store's
# address and matrix-ctl's identity, and retries on failure: a store
# that does not answer keeps the homeserver down until it does.
name = "the swarm registration is rendered before tuwunel and required by it, from the store, with retries";
ok =
let
r = baoWithMatrix.containers.hive-matrix.config.systemd.services.swarm-matrix-appservice-render;
@ -272,17 +274,19 @@ let
lib.elem "tuwunel.service" r.before
&& lib.elem "tuwunel.service" r.requiredBy
&& lib.hasSuffix "swarm-matrix-ctl appservice render" r.serviceConfig.ExecStart
&& !(r.environment ? BAO_ADDR);
&& r.environment.BAO_ADDR != ""
&& r.environment.BAO_CLIENT_CERT == "/var/lib/swarm-bao-pki/matrix-ctl.pem"
&& r.environment.MATRIX_APPSERVICE_CERT_ROLE == "swarm-matrix-ctl"
&& r.serviceConfig.Restart == "on-failure";
}
{
# The start path stays free of the store. The render is what tuwunel
# waits for and it carries no store address or identity; the sync unit
# that does is neither before tuwunel nor required by it, and tuwunel
# names it nowhere, so a store outage leaves the homeserver starting on
# the state dir's last copy. The presence arms are the render's own
# ordering (the same lookup finds `before`/`requiredBy` where they are)
# and the sync's order after the render.
name = "the sync unit is off tuwunel's start path and the render holds no store identity";
# The sync unit is what starts a homeserver the render's failure left
# down, so it must run when the render has failed: it is after the
# render, and neither requires nor binds to it. It stays off tuwunel's
# own start path, and tuwunel names it nowhere. The presence arms are the
# render's own ordering (the same lookup finds `before`/`requiredBy`
# where they are) and the sync's order after the render.
name = "the sync unit runs after the render without requiring it, and is off tuwunel's start path";
ok =
let
c = baoWithMatrix.containers.hive-matrix.config.systemd;
@ -298,15 +302,51 @@ let
(u.bindsTo or [ ])
];
sync = "swarm-matrix-appservice-sync.service";
render = "swarm-matrix-appservice-render.service";
in
lib.elem "tuwunel.service" r.before
&& lib.elem "swarm-matrix-appservice-render.service" s.after
&& lib.elem render s.after
&& !(lib.elem render (s.requires or [ ]))
&& !(lib.elem render (s.bindsTo or [ ]))
&& !(lib.elem "tuwunel.service" (s.before or [ ]))
&& !(lib.elem "tuwunel.service" (s.requiredBy or [ ]))
&& !(lib.elem "tuwunel.service" (s.wantedBy or [ ]))
&& !(lib.elem sync (names t))
&& !(lib.elem sync (r.before or [ ]))
&& !(lib.any (lib.hasPrefix "BAO_") (lib.attrNames r.environment));
&& !(lib.elem sync (r.before or [ ]));
}
{
# 🩸 The registration holds the tokens that create users, so it is
# rendered onto the container's tmpfs and no unit keeps the tokens in
# /var/lib. tuwunel's credential source, both units' runtime directory
# and the directory they are told to render into are one path under
# /run (the presence arms), and neither unit has a state directory or
# a writable path under /var/lib. The legacy directory is named in the
# environment, to be read, and nowhere else.
name = "the swarm registration is rendered under /run and no unit writes it under /var/lib";
ok =
let
c = baoWithMatrix.containers.hive-matrix.config.systemd;
units = [
c.services.swarm-matrix-appservice-render
c.services.swarm-matrix-appservice-sync
];
creds = c.services.tuwunel.serviceConfig.LoadCredential;
runDir = "/run/swarm-matrix-appservice";
writesVarLib =
u:
lib.any (lib.hasPrefix "/var/lib") (
lib.toList (u.serviceConfig.ReadWritePaths or [ ]) ++ lib.toList (u.serviceConfig.BindPaths or [ ])
)
|| (u.serviceConfig ? StateDirectory);
in
lib.elem "swarm-appservice.yaml:${runDir}/swarm.yaml" creds
&& lib.all (u: u.environment.MATRIX_APPSERVICE_RUNTIME_DIR == runDir) units
&& lib.all (u: u.serviceConfig.RuntimeDirectory == "swarm-matrix-appservice") units
&& !(lib.any writesVarLib units)
&& !(lib.any (cr: lib.hasInfix "/var/lib/swarm-matrix-appservice" cr) creds)
&& lib.all (
u: u.environment.MATRIX_APPSERVICE_LEGACY_DIR == "/var/lib/swarm-matrix-appservice"
) units;
}
{
# A timer repeats the sync, which needs a unit that does not stay