Host multiple conduit instances

This commit is contained in:
Natsu Kagami 2023-04-04 11:29:56 +02:00
parent f3b35486af
commit fc6f9f8987
Signed by: nki
GPG key ID: 7306B3D3C3AD6E51
4 changed files with 167 additions and 53 deletions

View file

@ -2,6 +2,24 @@
let
cfg = config.cloud.conduit;
defaultConfig = {
global = {
# Must be filled
# server_name = "";
# Must be filled
# port = "";
max_request_size = 20000000;
allow_registration = false;
allow_encryption = true;
allow_federation = true;
trusted_servers = [ "matrix.org" ];
address = "::1";
# Must be filled
# database_path = "";
database_backend = "rocksdb";
};
};
in
with lib;
{
@ -14,62 +32,132 @@ with lib;
default = pkgs.matrix-conduit;
};
host = mkOption {
type = types.str;
default = "m.nkagami.me";
};
port = mkOption {
type = types.int;
default = 6167;
};
allow_registration = mkOption {
type = types.bool;
default = false;
};
well-known_port = mkOption {
type = types.int;
default = 6166;
instances = mkOption {
type = types.attrsOf (types.submodule {
options = {
host = mkOption {
type = types.str;
};
server_name = mkOption {
type = types.str;
default = "";
};
port = mkOption {
type = types.int;
};
allow_registration = mkOption {
type = types.bool;
default = false;
};
well-known_port = mkOption {
type = types.int;
};
};
});
};
};
config.services.matrix-conduit = mkIf cfg.enable {
inherit (cfg) package;
enable = true;
settings.global = {
inherit (cfg) port allow_registration;
server_name = cfg.host;
database_backend = "rocksdb";
};
};
config.systemd.services = mkIf cfg.enable
(lib.attrsets.mapAttrs'
(name: instance: lib.attrsets.nameValuePair "matrix-conduit-${name}"
(
let
srvName = "matrix-conduit-${name}";
format = pkgs.formats.toml { };
server_name = if instance.server_name == "" then instance.host else instance.server_name;
configFile = format.generate "conduit.toml" (lib.attrsets.recursiveUpdate defaultConfig {
global.server_name = server_name;
global.port = instance.port;
global.allow_registration = instance.allow_registration;
global.database_path = "/var/lib/${srvName}/";
});
in
{
description = "Conduit Matrix Server (for ${server_name})";
documentation = [ "https://gitlab.com/famedly/conduit/" ];
wantedBy = [ "multi-user.target" ];
environment = { CONDUIT_CONFIG = configFile; };
serviceConfig = {
DynamicUser = true;
User = "${srvName}";
LockPersonality = true;
MemoryDenyWriteExecute = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateUsers = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
StateDirectory = "${srvName}";
ExecStart = "${cfg.package}/bin/conduit";
Restart = "on-failure";
RestartSec = 10;
StartLimitBurst = 5;
};
}
))
cfg.instances);
# Serving .well-known files
# This is a single .well-known/matrix/server file that points to the server,
# which is NOT on port 8448 since Cloudflare doesn't allow us to route HTTPS
# through that port.
config.services.nginx = mkIf cfg.enable {
enable = true;
virtualHosts.conduit-well-kwown = {
listen = [{ addr = "127.0.0.1"; port = cfg.well-known_port; }];
# Check https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/docs/configuring-well-known.md
# for the file structure.
root = pkgs.writeTextDir ".well-known/matrix/server" ''
{
"m.server": "${cfg.host}:443"
}
'';
config.services.nginx = mkIf cfg.enable
{
enable = true;
virtualHosts = lib.attrsets.mapAttrs'
(name: instance: lib.attrsets.nameValuePair "conduit-${name}-well-known" {
listen = [{ addr = "127.0.0.1"; port = instance.well-known_port; }];
# Check https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/docs/configuring-well-known.md
# for the file structure.
root = pkgs.symlinkJoin
{
name = "well-known-files-for-conduit-${name}";
paths = [
(pkgs.writeTextDir ".well-known/matrix/client" (builtins.toJSON {
"m.homeserver".base_url = "https://${instance.host}";
}))
(pkgs.writeTextDir ".well-known/matrix/server" (builtins.toJSON {
"m.server" = "${instance.host}:443";
}))
];
};
# Enable CORS from anywhere since we want all clients to find us out
extraConfig = ''
add_header 'Access-Control-Allow-Origin' "*";
'';
})
cfg.instances;
};
};
config.cloud.traefik.hosts = mkIf cfg.enable {
conduit = { inherit (cfg) port host; };
conduit-well-kwown = {
port = cfg.well-known_port;
filter = "Host(`${cfg.host}`) && PathPrefix(`/.well-known`)";
};
};
config.cloud.traefik.hosts = mkIf cfg.enable (
(lib.attrsets.mapAttrs'
(name: instance: lib.attrsets.nameValuePair "conduit-${name}" ({
inherit (instance) host port;
}))
cfg.instances)
// (lib.attrsets.mapAttrs'
(name: instance: lib.attrsets.nameValuePair "conduit-${name}-well-known" (
let
server_name = if instance.server_name == "" then instance.host else instance.server_name;
in
{
port = instance.well-known_port;
filter = "Host(`${server_name}`) && PathPrefix(`/.well-known`)";
}
))
cfg.instances)
);
}

View file

@ -16,6 +16,10 @@ with lib; {
description = "The port to listen to. Leave blank to just use the appserviceFile's configuration";
default = null;
};
homeserver = mkOption {
type = types.str;
description = "The homeserver to listen to";
};
};
config = mkIf cfg.enable (
let
@ -43,10 +47,7 @@ with lib; {
cfgFile
]
++ listenArgs
++ [
# Homeserver
"https://${toString cfgConduit.host}"
]
++ [ cfg.homeserver ]
);
# Hardening options