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:
parent
7813337548
commit
3a4b0ffabf
1 changed files with 594 additions and 378 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue