feat(conduit): Refactor appservices and add matrix-hookshot
This commit is contained in:
parent
3c7e1f106b
commit
31b2527e40
8 changed files with 306 additions and 91 deletions
configuration/services/conduit
|
@ -1,5 +1,4 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
|
@ -12,6 +11,11 @@ let
|
|||
turn-realm = "turn.${config.services.nginx.domain}";
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./heisenbridge.nix
|
||||
./matrix-hookshot.nix
|
||||
];
|
||||
|
||||
services.matrix-conduit = {
|
||||
enable = true;
|
||||
settings.global = {
|
||||
|
@ -40,91 +44,6 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
systemd.services.heisenbridge =
|
||||
let
|
||||
replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret";
|
||||
registrationFile = builtins.toFile "heisenbridge-registration.yaml" (
|
||||
builtins.toJSON {
|
||||
id = "heisenbridge";
|
||||
url = "http://127.0.0.1:9898";
|
||||
as_token = "@AS_TOKEN@";
|
||||
hs_token = "@HS_TOKEN@";
|
||||
rate_limited = false;
|
||||
sender_localpart = "heisenbridge";
|
||||
namespaces = {
|
||||
users = [
|
||||
{
|
||||
regex = "@irc_.*";
|
||||
exclusive = true;
|
||||
}
|
||||
{
|
||||
regex = "@heisenbridge:.*";
|
||||
exclusive = true;
|
||||
}
|
||||
];
|
||||
aliases = [ ];
|
||||
rooms = [ ];
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
# TODO(tlater): Starting with systemd 253 it will become possible
|
||||
# to do the credential setup as part of ExecStartPre/preStart
|
||||
# instead.
|
||||
#
|
||||
# This will also make it possible to actually set caps on the
|
||||
# heisenbridge process using systemd, so that we can run the
|
||||
# identd process.
|
||||
execScript = pkgs.writeShellScript "heisenbridge" ''
|
||||
cp ${registrationFile} "$RUNTIME_DIRECTORY/heisenbridge-registration.yaml"
|
||||
chmod 600 $RUNTIME_DIRECTORY/heisenbridge-registration.yaml
|
||||
${replaceSecretBin} '@AS_TOKEN@' "$CREDENTIALS_DIRECTORY/heisenbridge_as-token" "$RUNTIME_DIRECTORY/heisenbridge-registration.yaml"
|
||||
${replaceSecretBin} '@HS_TOKEN@' "$CREDENTIALS_DIRECTORY/heisenbridge_hs-token" "$RUNTIME_DIRECTORY/heisenbridge-registration.yaml"
|
||||
chmod 400 $RUNTIME_DIRECTORY/heisenbridge-registration.yaml
|
||||
|
||||
${pkgs.heisenbridge}/bin/heisenbridge \
|
||||
--config $RUNTIME_DIRECTORY/heisenbridge-registration.yaml \
|
||||
--owner @tlater:matrix.tlater.net \
|
||||
'http://localhost:${toString cfg.settings.global.port}'
|
||||
'';
|
||||
in
|
||||
{
|
||||
description = "Matrix<->IRC bridge";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "conduit.service" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
|
||||
LoadCredential = "heisenbridge:/run/secrets/heisenbridge";
|
||||
|
||||
ExecStart = execScript;
|
||||
|
||||
DynamicUser = true;
|
||||
RuntimeDirectory = "heisenbridge";
|
||||
RuntimeDirectoryMode = "0700";
|
||||
|
||||
RestrictNamespaces = true;
|
||||
PrivateUsers = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_INET AF_INET6" ];
|
||||
LockPersonality = true;
|
||||
RestrictRealtime = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
UMask = 77;
|
||||
|
||||
# For the identd port
|
||||
# CapabilityBoundingSet = ["CAP_NET_BIND_SERVICE"];
|
||||
# AmbientCapabilities = ["CAP_NET_BIND_SERVICE"];
|
||||
};
|
||||
};
|
||||
|
||||
# Pass in the TURN secret via EnvironmentFile, not supported by
|
||||
# upstream module currently.
|
||||
#
|
78
configuration/services/conduit/heisenbridge.nix
Normal file
78
configuration/services/conduit/heisenbridge.nix
Normal file
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
conduitCfg = config.services.matrix-conduit;
|
||||
matrixLib = pkgs.callPackage ./lib.nix { };
|
||||
in
|
||||
{
|
||||
systemd.services.heisenbridge =
|
||||
let
|
||||
registration = matrixLib.writeRegistrationScript {
|
||||
id = "heisenbridge";
|
||||
url = "http://127.0.0.1:9898";
|
||||
sender_localpart = "heisenbridge";
|
||||
|
||||
namespaces = {
|
||||
users = [
|
||||
{
|
||||
regex = "@irc_.*";
|
||||
exclusive = true;
|
||||
}
|
||||
{
|
||||
regex = "@heisenbridge:.*";
|
||||
exclusive = true;
|
||||
}
|
||||
];
|
||||
|
||||
aliases = [ ];
|
||||
rooms = [ ];
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
description = "Matrix<->IRC bridge";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "conduit.service" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
|
||||
LoadCredential = "heisenbridge:/run/secrets/heisenbridge";
|
||||
|
||||
inherit (registration) ExecStartPre;
|
||||
ExecStart = lib.concatStringsSep " " [
|
||||
"${lib.getExe pkgs.heisenbridge}"
|
||||
"--config \${RUNTIME_DIRECTORY}/heisenbridge-registration.yaml"
|
||||
"--owner @tlater:matrix.tlater.net"
|
||||
"http://localhost:${toString conduitCfg.settings.global.port}"
|
||||
];
|
||||
|
||||
DynamicUser = true;
|
||||
RuntimeDirectory = "heisenbridge";
|
||||
RuntimeDirectoryMode = "0700";
|
||||
|
||||
RestrictNamespaces = true;
|
||||
PrivateUsers = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_INET AF_INET6" ];
|
||||
LockPersonality = true;
|
||||
RestrictRealtime = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
UMask = 77;
|
||||
|
||||
# For the identd port
|
||||
# CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
|
||||
# AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
|
||||
};
|
||||
};
|
||||
}
|
66
configuration/services/conduit/lib.nix
Normal file
66
configuration/services/conduit/lib.nix
Normal file
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
lib,
|
||||
writeShellScript,
|
||||
formats,
|
||||
replace-secret,
|
||||
}:
|
||||
let
|
||||
replaceSecretBin = "${lib.getExe replace-secret}";
|
||||
in
|
||||
{
|
||||
# Write a script that will set up the service's registration.yaml
|
||||
# with secrets from systemd credentials.
|
||||
#
|
||||
# The credentials should be named `${id}_as-token` and
|
||||
# `${id}_hs-token`.
|
||||
#
|
||||
# This registration file needs to be manually added to conduit by
|
||||
# messaging the admin with the yaml file.
|
||||
#
|
||||
# TODO(tlater): Conduwuit seems to support a CLI interface for this,
|
||||
# may want to migrate to that sometime.
|
||||
writeRegistrationScript =
|
||||
{
|
||||
id, # Must be unique among all registered appservices/bots
|
||||
url, # The URL on which the service listens
|
||||
sender_localpart,
|
||||
rate_limited ? false,
|
||||
namespaces ? {
|
||||
aliases = [ ];
|
||||
rooms = [ ];
|
||||
users = [ ];
|
||||
},
|
||||
extraSettings ? { },
|
||||
# The location to place the file; assumes systemd runtime dir
|
||||
runtimeRegistration ? "$RUNTIME_DIRECTORY/${id}-registration.yaml",
|
||||
}:
|
||||
let
|
||||
registrationFile =
|
||||
(formats.yaml { }).generate "${id}-registration.yaml" {
|
||||
inherit
|
||||
id
|
||||
url
|
||||
sender_localpart
|
||||
rate_limited
|
||||
namespaces
|
||||
;
|
||||
|
||||
as_token = "@AS_TOKEN@";
|
||||
hs_token = "@HS_TOKEN@";
|
||||
}
|
||||
// extraSettings;
|
||||
in
|
||||
{
|
||||
inherit runtimeRegistration;
|
||||
ExecStartPre = writeShellScript "${id}-registration-setup.sh" ''
|
||||
cp -f ${registrationFile} "${runtimeRegistration}"
|
||||
chmod 600 "${runtimeRegistration}"
|
||||
|
||||
# Write actual secrets into config
|
||||
${replaceSecretBin} '@AS_TOKEN@' "$CREDENTIALS_DIRECTORY/${id}_as-token" "${runtimeRegistration}"
|
||||
${replaceSecretBin} '@HS_TOKEN@' "$CREDENTIALS_DIRECTORY/${id}_hs-token" "${runtimeRegistration}"
|
||||
|
||||
chmod 400 "${runtimeRegistration}"
|
||||
'';
|
||||
};
|
||||
}
|
142
configuration/services/conduit/matrix-hookshot.nix
Normal file
142
configuration/services/conduit/matrix-hookshot.nix
Normal file
|
@ -0,0 +1,142 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
matrixLib = pkgs.callPackage ./lib.nix { };
|
||||
|
||||
cfg = config.services.matrix-hookshot;
|
||||
conduitCfg = config.services.matrix-conduit;
|
||||
|
||||
address = "${config.services.matrix-hookshot.settings.bridge.bindAddress}";
|
||||
domain = "matrix.${config.services.nginx.domain}";
|
||||
port = config.services.matrix-hookshot.settings.bridge.port;
|
||||
|
||||
registration = matrixLib.writeRegistrationScript {
|
||||
id = "matrix-hookshot";
|
||||
url = "${address}:${toString port}";
|
||||
sender_localpart = "hookshot";
|
||||
|
||||
namespaces = {
|
||||
aliases = [ ];
|
||||
rooms = [ ];
|
||||
users = [
|
||||
{
|
||||
regex = "@${cfg.settings.generic.userIdPrefix}.*:${domain}";
|
||||
exclusive = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# Encryption support
|
||||
extraSettings = {
|
||||
"de.sorunome.msc2409.push_ephemeral" = true;
|
||||
push_ephemeral = true;
|
||||
"org.matrix.msc3202" = true;
|
||||
};
|
||||
|
||||
runtimeRegistration = "${cfg.registrationFile}";
|
||||
};
|
||||
in
|
||||
{
|
||||
systemd.services.matrix-hookshot = {
|
||||
serviceConfig = {
|
||||
Type = lib.mkForce "exec";
|
||||
|
||||
LoadCredential = "matrix-hookshot:/run/secrets/matrix-hookshot";
|
||||
inherit (registration) ExecStartPre;
|
||||
|
||||
# Some library in matrix-hookshot wants a home directory
|
||||
Environment = [ "HOME=/run/matrix-hookshot" ];
|
||||
|
||||
DynamicUser = true;
|
||||
StateDirectory = "matrix-hookshot";
|
||||
RuntimeDirectory = "matrix-hookshot";
|
||||
RuntimeDirectoryMode = "0700";
|
||||
|
||||
RestrictNamespaces = true;
|
||||
PrivateUsers = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_INET AF_INET6" ];
|
||||
LockPersonality = true;
|
||||
RestrictRealtime = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
UMask = 77;
|
||||
};
|
||||
};
|
||||
|
||||
services.matrix-hookshot = {
|
||||
enable = true;
|
||||
|
||||
serviceDependencies = [
|
||||
"conduit.service"
|
||||
];
|
||||
|
||||
registrationFile = "/run/matrix-hookshot/registration.yaml";
|
||||
|
||||
settings = {
|
||||
bridge = {
|
||||
inherit domain;
|
||||
url = "http://localhost:${toString conduitCfg.settings.global.port}";
|
||||
mediaUrl = conduitCfg.settings.global.well_known.client;
|
||||
port = 9993;
|
||||
bindAddress = "127.0.0.1";
|
||||
};
|
||||
|
||||
generic = {
|
||||
enabled = true;
|
||||
outbound = false;
|
||||
# Only allow webhooks from localhost for the moment
|
||||
urlPrefix = "${cfg.settings.bridge.url}/webhook";
|
||||
userIdPrefix = "_webhooks_";
|
||||
};
|
||||
|
||||
encryption.storagePath = "/var/lib/matrix-hookshot/cryptostore";
|
||||
|
||||
permissions = [
|
||||
{
|
||||
actor = "matrix.tlater.net";
|
||||
services = [
|
||||
{
|
||||
service = "*";
|
||||
level = "notifications";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
actor = "@tlater:matrix.tlater.net";
|
||||
services = [
|
||||
{
|
||||
service = "*";
|
||||
level = "admin";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
listeners = [
|
||||
{
|
||||
port = 9000;
|
||||
resources = [
|
||||
"webhooks"
|
||||
];
|
||||
}
|
||||
{
|
||||
port = 9001;
|
||||
resources = [
|
||||
"metrics"
|
||||
"provisioning"
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue