matrix: drop the per-hive appservice and its unused token
Every hive's homeserver loaded a per-hive `hyperhive` appservice
registration, and the swarm minted and delivered an as_token for it
through bao. No client presented that token: swarm-controller creates
every `@hive-<hive>` sender and every agent account with the swarm
appservice token (hive_sender.rs, agent_token.rs), and no Rust code read
the per-hive one.
Removed, with everything that existed only to serve it:
- hive-matrix.nix: the `hyperhive` registration, its activation-time
render, the host bind mount of /var/lib/hyperhive/matrix-appservice,
its LoadCredential entry, and the internal options
`deploy.matrix.appserviceTokenFile` / `appserviceRegistrationScript`.
tuwunel now loads only the swarm registration.
- glue-matrix-bao-token.nix and its `swarm-bao-matrix-token` unit.
- glue-bao-tls.nix: the matrix-token leaf and its defaults.
- swarm-bao.nix: the `swarm-matrix-token-<hive>` roles and policies
(`swarm-bao-matrix-token-policy`), and the options
`deploy.bao.matrixTokenClient{Cert,Key}File` and
`matrixTokenCommonNamePrefix`, now mkRemovedOptionModule.
- swarm-secret-publisher.nix: the per-hive token mint and its state dir.
- swarm.nix: the reserved `<matrixTokenCommonNamePrefix>-<hive>` CN.
- swarm-secret-client: `matrix::appservice_token_path`.
The swarm registration (swarm-matrix-ctl, swarm-controller) is untouched.
Comments and docs that pointed at the removed glue file now point at
glue-queue-agent-credential.nix, which has the same reader shape.
Refs #4428
This commit is contained in:
parent
e4b170f8c6
commit
48067d07e8
31 changed files with 362 additions and 1233 deletions
|
|
@ -50,79 +50,20 @@ let
|
|||
# visible to the service after sandboxing (ReadWritePaths / ProtectHome),
|
||||
# typically by placing the file under /etc/tuwunel/" — which this
|
||||
# container has no writable etc for. `LoadCredential` is the answer
|
||||
# already in use for the appservice registration below, and for the
|
||||
# already in use for the swarm appservice registration below, and for the
|
||||
# same reason: it keeps `DynamicUser=true` + `PrivateUsers=true` intact
|
||||
# with no host-side chown or GID pinning.
|
||||
matrixSecretCredential = "/run/credentials/tuwunel.service/oidc_client_secret";
|
||||
|
||||
# The hive's appservice registration, whose `url` is null. Null is a legal
|
||||
# `url` (ruma's `Registration` types it `Option<String>`), and it is the
|
||||
# whole point — with no URL the homeserver
|
||||
# never calls out, so there is no HTTP service to run and no daemon to
|
||||
# operate. tuwunel loads the registration and creates its sender account
|
||||
# (below). No client presents its `as_token`: `swarm-controller` mints the
|
||||
# sender's token with the swarm registration's.
|
||||
appserviceId = "hyperhive";
|
||||
|
||||
# The appservice's own user, and the account the hive acts as. An
|
||||
# ordinary user, not a homeserver admin: everything the hive does with
|
||||
# it — the Space, the chat room, the invites — it does as the creator of
|
||||
# those rooms. Loading a registration CREATES its `sender_localpart` user
|
||||
# when absent (tuwunel `src/service/appservice/mod.rs`), on a zero-user
|
||||
# database, inside `Services::start()` — before the HTTP listener accepts
|
||||
# anything, so the account exists on the very first boot of a fresh
|
||||
# homeserver without hive-c0re racing to register it.
|
||||
# Where tuwunel reads appservice registrations from: its own credentials
|
||||
# directory. A registration is a 0600 root-owned file and the homeserver
|
||||
# runs under `DynamicUser=true`, so `LoadCredential` copies it to a 0400
|
||||
# dynamic-user-owned path as root, before the sandbox and that user exist.
|
||||
#
|
||||
# 🩸 **Derived from the hive name, so it is one account per hive.** It was
|
||||
# the bare `hive` and a swarm runs one homeserver: every hive on it acted
|
||||
# as the same `@hive:`, which is one identity with no attribution and no
|
||||
# way to revoke a single hive. The hives that do not run this container
|
||||
# register their own `hive-<name>` through the appservice namespace below,
|
||||
# which already admits it.
|
||||
#
|
||||
# ⚠️ Must equal `swarm_secret_client::matrix::hive_localpart`, which
|
||||
# hive-c0re and swarm-controller both derive from independently with
|
||||
# nothing wiring an override across — same agreement, and same reason for
|
||||
# saying so, as the token path below.
|
||||
#
|
||||
# `hiveName` has no fallback here for the reason ./glue-matrix-bao-token.nix
|
||||
# gives at its own use of it: it is asserted set on every host that runs the
|
||||
# homeserver.
|
||||
hiveLocalpart = "hive-${toString config.services.hyperhive.hiveName}";
|
||||
|
||||
# The `as_token`, and the `hs_token` the spec requires alongside it. Both
|
||||
# minted by the render script below, mode 0600; the `as_token` is the one
|
||||
# the swarm secret store overwrites (see
|
||||
# `glue-matrix-bao-token.nix`). The `hs_token` authenticates the homeserver
|
||||
# TO the appservice, which with `url = null` is nobody — it exists because
|
||||
# the registration format requires it.
|
||||
#
|
||||
# `appserviceTokenPath` is the single source for the option's `default`,
|
||||
# its `config`-level `mkDefault` self-definition, and the assertion that
|
||||
# rejects a moved path. See `appserviceTokenFile`'s own comment below.
|
||||
appserviceTokenPath = "/var/lib/hyperhive/matrix-appservice-token";
|
||||
appserviceHsTokenPath = "/var/lib/hyperhive/matrix-appservice-hs-token";
|
||||
|
||||
# The registration file, and the directory that holds it. A directory
|
||||
# rather than a `[global.appservice.<id>]` stanza because a stanza's
|
||||
# `as_token` would be a nix literal, and a nix literal is a world-readable
|
||||
# store path — the same rule that sends the OIDC client secret through a
|
||||
# runtime file. `docs/swarm/secrets.md` has the general form of it.
|
||||
appserviceDir = "/var/lib/hyperhive/matrix-appservice";
|
||||
appserviceRegistrationPath = "${appserviceDir}/${appserviceId}.yaml";
|
||||
|
||||
# ⚠️ tuwunel does not read the host path directly, for exactly the reason
|
||||
# given for the two secrets above: the file is 0600 root-owned and the
|
||||
# homeserver runs under `DynamicUser=true`. `LoadCredential` copies it to a
|
||||
# 0400 dynamic-user-owned path as root, before the sandbox and that user
|
||||
# exist.
|
||||
#
|
||||
# So `appservice_dir` points at the credentials directory ITSELF. That is
|
||||
# safe rather than clever: tuwunel's loader takes only `.yaml`/`.yml`
|
||||
# Safe rather than clever: tuwunel's loader takes only `.yaml`/`.yml`
|
||||
# entries from the directory and skips every other file, so the sibling
|
||||
# credentials (the OIDC secret) are invisible to it. A credential id is a
|
||||
# free-form filename, which is what lets ours end in `.yaml`.
|
||||
appserviceCredentialId = "${appserviceId}-appservice.yaml";
|
||||
# free-form filename, which is what lets a registration's end in `.yaml`.
|
||||
appserviceCredentialDir = "/run/credentials/tuwunel.service";
|
||||
|
||||
# ── swarm-matrix-ctl ────────────────────────────────────────────────
|
||||
|
|
@ -147,9 +88,8 @@ let
|
|||
# derived rather than assumed, because an operator naming paths by hand is
|
||||
# exactly the deployment the gate above is written for.
|
||||
#
|
||||
# Directories rather than the files, for the reason `appserviceDir`'s own
|
||||
# comment gives: a re-issued leaf is a new inode, and binding the file would
|
||||
# pin the one the container saw when it started.
|
||||
# Directories rather than the files: a re-issued leaf is a new inode, and
|
||||
# binding the file would pin the one the container saw when it started.
|
||||
ctlPkiDirs = lib.optionals ctlActive (
|
||||
lib.unique (
|
||||
map builtins.dirOf (
|
||||
|
|
@ -169,9 +109,9 @@ let
|
|||
|
||||
# ── the swarm's own appservice ──────────────────────────────────────
|
||||
#
|
||||
# A second registration beside the hive's `hyperhive` one, and the swarm's
|
||||
# identity on this homeserver: `swarm-controller` creates every agent's
|
||||
# account with its token. Minted INSIDE this container by
|
||||
# The homeserver's one appservice registration, and the swarm's identity on
|
||||
# it: `swarm-controller` creates every agent's account and every hive's
|
||||
# `@hive-<hive>` sender with its token. Minted INSIDE this container by
|
||||
# `swarm-matrix-ctl appservice render` and published to the store by
|
||||
# `appservice publish`, which is why it is gated on matrix-ctl's store
|
||||
# identity: with nobody to publish it, a registration here would be an
|
||||
|
|
@ -187,8 +127,8 @@ let
|
|||
swarmAppserviceDir = "/var/lib/swarm-matrix-appservice";
|
||||
swarmAppserviceCredentialId = "swarm-appservice.yaml";
|
||||
|
||||
# Every local user this hive may provision — agents and `@hive-<hive>:`
|
||||
# itself — which is the whole matrix localpart charset.
|
||||
# Every local user the swarm appservice may create — agents and every
|
||||
# hive's `@hive-<hive>:` sender — which is the whole matrix localpart charset.
|
||||
#
|
||||
# ⚠️ Anchored deliberately: tuwunel compiles a namespace into a `RegexSet`
|
||||
# and asks it for a MATCH, not a full match, so an unanchored
|
||||
|
|
@ -201,73 +141,6 @@ let
|
|||
# create these names, not a monopoly on them.
|
||||
appserviceUserRegex = "^@[a-z0-9._=/-]+:${lib.escapeRegex effectiveServerName}$";
|
||||
|
||||
# Mint the tokens if they are absent, then render the registration from
|
||||
# whatever they now hold. **One script with two callers** — the activation
|
||||
# script below and `glue-matrix-bao-token.nix`, which overwrites the
|
||||
# `as_token` with the swarm store's copy and has to re-render afterwards.
|
||||
#
|
||||
# ⚠️ The `as_token` mint here is the FIRST-BOOT FALLBACK, not the normal
|
||||
# route. `swarm-secret-publisher.nix` mints one per hive swarm-side and
|
||||
# publishes it to the store; the reader above overwrites this file before
|
||||
# the homeserver's container starts, so what a hive actually runs on is the
|
||||
# swarm's value. This keeps a hive that has never reached the store working
|
||||
# — and it fires only when the file is absent, so it never clobbers one the
|
||||
# store delivered. (`hs_token` has no swarm half: it is how the homeserver
|
||||
# authenticates to *us*, so it stays hive-local and is minted here for real.)
|
||||
# A second copy of the registration's shape would be a second source of
|
||||
# truth for a format whose mismatch is silent: the homeserver would load a
|
||||
# registration naming a token nobody holds, and every request hive-c0re
|
||||
# makes would come back 401 naming nothing.
|
||||
#
|
||||
# Re-rendering unconditionally is the point rather than thoroughness: "the
|
||||
# token file exists" does not mean "the registration carries what is in
|
||||
# it".
|
||||
appserviceRegistrationScript = pkgs.writeShellApplication {
|
||||
name = "hive-matrix-appservice-registration";
|
||||
runtimeInputs = [ pkgs.coreutils ];
|
||||
text = ''
|
||||
# Both the tokens and the rendered registration are secrets; 077
|
||||
# covers every file this script creates rather than each one
|
||||
# separately.
|
||||
umask 077
|
||||
mkdir -p ${lib.escapeShellArg appserviceDir}
|
||||
for f in ${lib.escapeShellArg appserviceTokenPath} ${lib.escapeShellArg appserviceHsTokenPath}; do
|
||||
if [ ! -s "$f" ]; then
|
||||
head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "$f"
|
||||
echo >> "$f"
|
||||
echo "hive-matrix: generated appservice token at $f"
|
||||
fi
|
||||
chmod 0600 "$f"
|
||||
done
|
||||
|
||||
# Read into shell variables and emitted with `printf`, a shell
|
||||
# builtin: a token passed as an argument to a real command would land
|
||||
# in that process's argv, which is world-readable for its lifetime.
|
||||
asToken="$(cat ${lib.escapeShellArg appserviceTokenPath})"
|
||||
hsToken="$(cat ${lib.escapeShellArg appserviceHsTokenPath})"
|
||||
|
||||
# The quoted heredoc keeps the regex's own `$` and `\` out of the
|
||||
# shell's hands; the YAML single quotes keep them out of YAML's.
|
||||
{
|
||||
cat <<'REGISTRATION'
|
||||
id: ${appserviceId}
|
||||
url: null
|
||||
sender_localpart: ${hiveLocalpart}
|
||||
rate_limited: false
|
||||
namespaces:
|
||||
users:
|
||||
- exclusive: false
|
||||
regex: '${appserviceUserRegex}'
|
||||
aliases: []
|
||||
rooms: []
|
||||
REGISTRATION
|
||||
printf 'as_token: %s\nhs_token: %s\n' "$asToken" "$hsToken"
|
||||
} > ${lib.escapeShellArg appserviceRegistrationPath}
|
||||
chmod 0600 ${lib.escapeShellArg appserviceRegistrationPath}
|
||||
chmod 0700 ${lib.escapeShellArg appserviceDir}
|
||||
'';
|
||||
};
|
||||
|
||||
# Format-locked by tuwunel, not chosen here: the callback host must point
|
||||
# directly at the matrix server and the path is fixed at
|
||||
# `/_matrix/client/unstable/login/sso/callback/<client_id>`. Built once
|
||||
|
|
@ -482,61 +355,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
appserviceTokenFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
internal = true;
|
||||
default = appserviceTokenPath;
|
||||
description = ''
|
||||
Host path to a file containing this hive's matrix appservice
|
||||
token (`as_token`). Minted automatically on first activation
|
||||
(32-byte random hex, mode 0600) and rendered into the
|
||||
appservice registration the homeserver loads at boot. Agents
|
||||
never see it; an agent only ever receives its own
|
||||
`access_token`.
|
||||
|
||||
Not operator-settable — the module's registration renderer reads
|
||||
this same path as a literal, not through the option,
|
||||
with nothing wiring an override across, so a moved path desyncs
|
||||
the two silently. An externally-managed token is delivered by
|
||||
writing into *this* fixed path instead of moving it — see
|
||||
`glue-matrix-bao-token.nix`, which fetches from the swarm secret
|
||||
store, overwrites this file in place, and re-renders the
|
||||
registration that names it.
|
||||
|
||||
Enforced by an `assertions` entry below rather than `readOnly`:
|
||||
the `config` block gives this option its own `mkDefault`
|
||||
definition (lowest priority) so a real override still resolves
|
||||
cleanly instead of crashing eval with nixpkgs' generic
|
||||
"read-only, set multiple times" message; the assertion then
|
||||
names the actual problem. (`readOnly` was the first attempt on
|
||||
this option's predecessor — atlas caught that it only rejects a
|
||||
*second* definition, so with nothing else defining the option a
|
||||
lone override sailed through silently, same desync as before
|
||||
with a lock that wasn't locked. Fixed by defining the value here
|
||||
instead of leaving it on `default` alone, but a proper
|
||||
`assertions` message beat re-adding `readOnly` on top once the
|
||||
option had a real definition either way.)
|
||||
'';
|
||||
};
|
||||
|
||||
appserviceRegistrationScript = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
internal = true;
|
||||
default = "${appserviceRegistrationScript}/bin/hive-matrix-appservice-registration";
|
||||
defaultText = lib.literalMD "the module's own registration renderer";
|
||||
description = ''
|
||||
The script that mints the appservice tokens when absent and
|
||||
(re-)renders the registration file from them. An option only so
|
||||
that `glue-matrix-bao-token.nix` can run the same one after
|
||||
overwriting the token with the swarm store's copy, rather than
|
||||
carrying a second copy of the registration's shape.
|
||||
|
||||
Not operator-settable, and not a hook: replacing it means
|
||||
deciding what the homeserver's appservice registration says,
|
||||
which is this module's job.
|
||||
'';
|
||||
};
|
||||
|
||||
gui.package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = fluffychat-web-fixed;
|
||||
|
|
@ -629,13 +447,6 @@ in
|
|||
};
|
||||
|
||||
config = lib.mkIf deployCfg.matrix.enable {
|
||||
# The option's own value, defined explicitly rather than left on its
|
||||
# bare `default` — `mkDefault` so a real override still resolves
|
||||
# cleanly rather than crashing eval; the `assertions` entry below is
|
||||
# what actually rejects it, with a message naming the reason. See that
|
||||
# option's own comment above.
|
||||
services.hyperhive.deploy.matrix.appserviceTokenFile = lib.mkDefault appserviceTokenPath;
|
||||
|
||||
# Matrix's own gateway surface: the sub-domain vhost, the name the
|
||||
# hive resolver answers for, and the Accept-header map that vhost's
|
||||
# SPA fallback reads. All three are matrix knowledge and none of
|
||||
|
|
@ -769,25 +580,6 @@ in
|
|||
httpPort and has no such name.
|
||||
'';
|
||||
}
|
||||
{
|
||||
# mkDefault above lets an override resolve instead of crashing
|
||||
# eval — this is the actual rejection, with a message that names
|
||||
# the real fix instead of nixpkgs' generic conflicting-definition
|
||||
# text.
|
||||
assertion = deployCfg.matrix.appserviceTokenFile == appserviceTokenPath;
|
||||
message = ''
|
||||
services.hyperhive.deploy.matrix.appserviceTokenFile is fixed at
|
||||
${appserviceTokenPath} and cannot be moved — the registration
|
||||
renderer reads this same path as a literal and has no way to learn
|
||||
an override, so moving it desyncs the two silently instead of
|
||||
loudly.
|
||||
|
||||
Integrating an externally-managed appservice token? Deliver it
|
||||
by writing into ${appserviceTokenPath} instead of pointing this
|
||||
option elsewhere — see glue-matrix-bao-token.nix, which does
|
||||
exactly that from the swarm secret store.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
# One declaration, two readers. The homeserver knows its own callback
|
||||
|
|
@ -829,11 +621,10 @@ in
|
|||
# permanent stall presenting as "matrix is broken", several layers from
|
||||
# its cause.
|
||||
#
|
||||
# The appservice registration dodges that with an activation script
|
||||
# that renders the file first. ⚠️ That dodge is NOT available here:
|
||||
# tuwunel requires the secret file to exist *and be non-empty*, so a
|
||||
# zero-byte placeholder would satisfy the bind mount and then stop the
|
||||
# homeserver from starting.
|
||||
# ⚠️ Rendering a placeholder first is no way around it: tuwunel
|
||||
# requires the secret file to exist *and be non-empty*, so a zero-byte
|
||||
# placeholder would satisfy the bind mount and then stop the homeserver
|
||||
# from starting.
|
||||
systemd.services.hive-matrix-oidc-secret = lib.mkIf ssoLocal {
|
||||
description = "deliver the homeserver's OIDC client secret from authelia";
|
||||
after = [ "container@${autheliaCfg.machine}.service" ];
|
||||
|
|
@ -938,23 +729,6 @@ in
|
|||
''
|
||||
);
|
||||
|
||||
# Mint the appservice tokens and render the registration, before any
|
||||
# container start.
|
||||
#
|
||||
# An activation script rather than a unit: the directory below is
|
||||
# bind-mounted into the container and nixos-container refuses to start
|
||||
# when a bind source is missing, so this has to have run first.
|
||||
# Activation is what runs before the container both on a switch and on
|
||||
# every boot. (The registration token this replaced used an activation
|
||||
# script for the same reason, and additionally to dodge nspawn creating
|
||||
# an empty file at a missing bind target — which tuwunel then read as
|
||||
# "no token", refusing every registration until the next restart. A
|
||||
# missing registration file is not silent in that way: the homeserver
|
||||
# fails its appservice load loudly.)
|
||||
system.activationScripts.hive-matrix-appservice = lib.stringAfter [ "var" ] ''
|
||||
${deployCfg.matrix.appserviceRegistrationScript}
|
||||
'';
|
||||
|
||||
containers.hive-matrix = {
|
||||
autoStart = true;
|
||||
ephemeral = false;
|
||||
|
|
@ -962,23 +736,12 @@ in
|
|||
# --link-journal=try-guest, and EXTRA_NSPAWN_FLAGS expands after it.
|
||||
extraFlags = [ "--link-journal=host" ];
|
||||
inherit privateNetwork;
|
||||
# Read-only bind of the host-managed appservice registration; tuwunel
|
||||
# reads it via systemd LoadCredential below (not directly).
|
||||
#
|
||||
# The directory, not the file inside it: the registration is
|
||||
# re-rendered rather than edited, and binding the file would pin the
|
||||
# inode the container saw when it started.
|
||||
bindMounts = {
|
||||
${appserviceDir} = {
|
||||
hostPath = appserviceDir;
|
||||
isReadOnly = true;
|
||||
};
|
||||
}
|
||||
// caTrust.bindMount
|
||||
# matrix-ctl's bao client identity, and nothing else of the hive's. See
|
||||
# `ctlPkiDirs` above for why it is a derived set of directories
|
||||
# rather than one literal.
|
||||
// ctlBindMounts;
|
||||
bindMounts =
|
||||
caTrust.bindMount
|
||||
# matrix-ctl's bao client identity, and nothing else of the hive's. See
|
||||
# `ctlPkiDirs` above for why it is a derived set of directories
|
||||
# rather than one literal.
|
||||
// ctlBindMounts;
|
||||
config =
|
||||
{ ... }:
|
||||
{
|
||||
|
|
@ -1061,10 +824,10 @@ in
|
|||
allow_federation = true;
|
||||
trusted_servers = deployCfg.matrix.trustedServers;
|
||||
# Nobody registers themselves here. Accounts are created by
|
||||
# the hive's appservice, which this flag does not gate —
|
||||
# the swarm's appservice, which this flag does not gate —
|
||||
# tuwunel checks it only for requests that arrive WITHOUT an
|
||||
# appservice token, so hive-c0re provisions exactly as before
|
||||
# and everyone else is refused outright.
|
||||
# appservice token, so swarm-controller provisions and
|
||||
# everyone else is refused outright.
|
||||
#
|
||||
# ⚠️ Not a hardening afterthought: `allow_registration = true`
|
||||
# with no registration token configured makes tuwunel REFUSE
|
||||
|
|
@ -1074,7 +837,7 @@ in
|
|||
# homeserver, it is a homeserver that does not boot.
|
||||
allow_registration = false;
|
||||
|
||||
# Where the hive's appservice registration is read from — the
|
||||
# Where the swarm's appservice registration is read from — the
|
||||
# credentials directory, for the reasons at
|
||||
# `appserviceCredentialDir`'s own definition. Loaded inside
|
||||
# `Services::start()`, before the listener accepts anything.
|
||||
|
|
@ -1083,8 +846,8 @@ in
|
|||
}
|
||||
# Exactly one account is promoted to homeserver admin at boot:
|
||||
# the swarm appservice's sender. Its token is read by
|
||||
# matrix-ctl and swarm-controller only. `@${hiveLocalpart}`
|
||||
# stays an ordinary user, because every hive reads its
|
||||
# matrix-ctl and swarm-controller only. Each `@hive-<hive>`
|
||||
# stays an ordinary user, because its hive reads its
|
||||
# credential; what it does (the Space, the chat room, the
|
||||
# invites) rides on being the rooms' creator, not on admin.
|
||||
#
|
||||
|
|
@ -1161,20 +924,15 @@ in
|
|||
# host-side chown :tuwunel / GID-pin gymnastics needed.
|
||||
# See `man systemd.exec` → LoadCredential.
|
||||
systemd.services.tuwunel.serviceConfig.LoadCredential = [
|
||||
# The credential id carries a `.yaml` suffix on purpose:
|
||||
# `appservice_dir` above names this very directory, and tuwunel
|
||||
# takes only `.yaml`/`.yml` entries from it.
|
||||
"${appserviceCredentialId}:${appserviceRegistrationPath}"
|
||||
# Same mechanism, second secret. tuwunel re-reads this file on
|
||||
# every OAuth exchange, not just at startup, so it has to
|
||||
# tuwunel re-reads this file on every OAuth exchange, not just at startup, so it has to
|
||||
# outlive the unit's start — a credentials path does.
|
||||
"oidc_client_secret:${toString deployCfg.matrix.sso.clientSecretFile}"
|
||||
]
|
||||
# The swarm registration, a second `.yaml` in the same directory:
|
||||
# tuwunel loads every one it finds (`appservice/mod.rs`), and
|
||||
# refuses only a duplicate `id` or `as_token`, never an
|
||||
# overlapping namespace. A missing source fails this unit, which
|
||||
# is why the render below is `requiredBy` it and local only.
|
||||
# The swarm registration. The credential id carries a `.yaml`
|
||||
# suffix on purpose: `appservice_dir` above names this very
|
||||
# directory, and tuwunel takes only `.yaml`/`.yml` entries from
|
||||
# it. A missing source fails this unit, which is why the render
|
||||
# below is `requiredBy` it and local only.
|
||||
++ lib.optional ctlActive "${swarmAppserviceCredentialId}:${swarmAppserviceDir}/swarm.yaml";
|
||||
|
||||
# The swarm registration, minted and rendered before the homeserver
|
||||
|
|
@ -1196,9 +954,8 @@ in
|
|||
environment = {
|
||||
MATRIX_APPSERVICE_DIR = swarmAppserviceDir;
|
||||
MATRIX_APPSERVICE_SENDER = swarmSenderLocalpart;
|
||||
# The hive registration's namespace. Agents' localparts are
|
||||
# bare `[a-z0-9-]`, so nothing narrower covers them without
|
||||
# also covering people.
|
||||
# Agents' localparts are bare `[a-z0-9-]`, so nothing narrower
|
||||
# covers them without also covering people.
|
||||
MATRIX_APPSERVICE_USER_REGEX = appserviceUserRegex;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue