264 lines
7.3 KiB
Nix
264 lines
7.3 KiB
Nix
{
|
|
inputs,
|
|
flake,
|
|
self,
|
|
}:
|
|
{
|
|
pkgs,
|
|
lib,
|
|
config,
|
|
...
|
|
}: let
|
|
cfg = config.hectic.services.matrix;
|
|
matrixUsers = builtins.attrNames cfg.users;
|
|
mkUserRegistration = name: let
|
|
user = cfg.users.${name};
|
|
adminFlag = if user.admin then "--admin" else "--no-admin";
|
|
in ''
|
|
if [ ! -r "${user.passwordFile}" ]; then
|
|
printf 'Missing Matrix password file for %s: %s\n' '${name}' '${user.passwordFile}' >&2
|
|
exit 1
|
|
fi
|
|
|
|
${pkgs.matrix-synapse}/bin/register_new_matrix_user \
|
|
-u '${name}' \
|
|
-p "$(tr -d '\n' < "${user.passwordFile}")" \
|
|
-k "$REGISTRATION_SHARED_SECRET" \
|
|
${adminFlag} \
|
|
http://127.0.0.1:8008 || true
|
|
'';
|
|
in {
|
|
options = {
|
|
hectic.services.matrix = {
|
|
enable = lib.mkEnableOption "Matrix Synapse homeserver with PostgreSQL and nginx";
|
|
secretsFile = lib.mkOption {
|
|
type = lib.types.path;
|
|
description = ''
|
|
path to env file with matrix secrets
|
|
|
|
content:
|
|
registration_shared_secret:
|
|
macroon_secret_key
|
|
form_secret
|
|
'';
|
|
};
|
|
postgresql = {
|
|
port = lib.mkOption {
|
|
type = lib.types.port;
|
|
default = 5432;
|
|
description = ''
|
|
postgres port
|
|
'';
|
|
};
|
|
initialEnvFile = lib.mkOption {
|
|
type = lib.types.path;
|
|
description = ''
|
|
path to env file with postgresql initial secrets
|
|
|
|
content:
|
|
POSTGRESQL_PASSWORD=
|
|
'';
|
|
};
|
|
};
|
|
matrixDomain = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = ''
|
|
domain to matrix
|
|
'';
|
|
};
|
|
maxUploadSize = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "100M";
|
|
description = ''
|
|
Maximum file upload size accepted by Synapse and nginx.
|
|
'';
|
|
};
|
|
users = lib.mkOption {
|
|
type = lib.types.attrsOf (lib.types.submodule {
|
|
options = {
|
|
passwordFile = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = ''
|
|
Full path to a file containing the Matrix user's password.
|
|
'';
|
|
};
|
|
admin = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to create the Matrix user as an admin.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = {};
|
|
description = ''
|
|
Declarative Matrix users to provision after Synapse starts.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
config = lib.mkIf cfg.enable {
|
|
services.matrix-synapse = {
|
|
enable = true;
|
|
extraConfigFiles = [
|
|
cfg.secretsFile
|
|
];
|
|
settings = {
|
|
server_name = cfg.matrixDomain;
|
|
public_baseurl = "https://${cfg.matrixDomain}";
|
|
max_upload_size = cfg.maxUploadSize;
|
|
experimental_features = {
|
|
msc3266_enabled = true;
|
|
msc4140_enabled = true;
|
|
msc4143_enabled = true;
|
|
msc4222_enabled = true;
|
|
};
|
|
matrix_rtc = {
|
|
transports = [
|
|
{
|
|
type = "livekit";
|
|
livekit_service_url = "https://${cfg.matrixDomain}/livekit/jwt";
|
|
}
|
|
];
|
|
};
|
|
listeners = [
|
|
{
|
|
port = 8008;
|
|
bind_addresses = [ "0.0.0.0" ];
|
|
type = "http";
|
|
tls = false;
|
|
resources = [
|
|
{
|
|
names = [
|
|
"client"
|
|
# Ability speak between different matrix servers and get
|
|
# global id, requires .well-known
|
|
"federation"
|
|
"openid"
|
|
];
|
|
compress = false;
|
|
}
|
|
];
|
|
}
|
|
];
|
|
|
|
enable_registration = true;
|
|
enable_registration_without_verification = true;
|
|
|
|
};
|
|
};
|
|
|
|
environment.systemPackages = [
|
|
pkgs.matrix-synapse
|
|
];
|
|
|
|
services.postgresql = {
|
|
enable = true;
|
|
package = pkgs.postgresql_17;
|
|
|
|
initdbArgs = [
|
|
"--locale=C"
|
|
"--encoding=UTF8"
|
|
];
|
|
|
|
enableTCPIP = true;
|
|
settings.port = cfg.postgresql.port;
|
|
authentication = builtins.concatStringsSep "\n" [
|
|
"local all all trust"
|
|
"host sameuser all 127.0.0.1/32 scram-sha-256"
|
|
"host sameuser all ::1/128 scram-sha-256"
|
|
"host all all ::1/128 scram-sha-256"
|
|
"host all all 0.0.0.0/0 scram-sha-256"
|
|
|
|
"host replication postgres 127.0.0.1/32 scram-sha-256"
|
|
"host replication postgres ::1/128 scram-sha-256"
|
|
];
|
|
|
|
settings = {
|
|
wal_level = "replica";
|
|
max_wal_senders = 10;
|
|
};
|
|
|
|
ensureUsers = [
|
|
{
|
|
name = "matrix-synapse";
|
|
ensureClauses.login = true;
|
|
ensureDBOwnership = true;
|
|
}
|
|
];
|
|
|
|
ensureDatabases = [
|
|
"matrix-synapse"
|
|
];
|
|
|
|
initialScript = pkgs.writeText "init-sql-script" ''
|
|
-- setup password from env/sops
|
|
DO $$#!${pkgs.dash}/bin/dash
|
|
set -e
|
|
. ${cfg.postgresql.initialEnvFile}
|
|
psql -Atc "ALTER USER postgres WITH PASSWORD '$POSTGRESQL_PASSWORD'";
|
|
$$ LANGUAGE plsh;
|
|
|
|
CREATE ROLE myuser LOGIN PASSWORD 'matrix-synapse';
|
|
'';
|
|
};
|
|
|
|
services.nginx = {
|
|
enable = true;
|
|
virtualHosts.${cfg.matrixDomain} = {
|
|
forceSSL = true;
|
|
enableACME = true;
|
|
locations."/" = {
|
|
proxyPass = "http://127.0.0.1:8008";
|
|
extraConfig = ''
|
|
client_max_body_size ${cfg.maxUploadSize};
|
|
'';
|
|
};
|
|
locations."=/.well-known/matrix/server" = {
|
|
extraConfig = ''
|
|
default_type application/json;
|
|
add_header Access-Control-Allow-Origin *;
|
|
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
|
|
add_header Access-Control-Allow-Headers "X-Requested-With, Content-Type, Authorization";
|
|
'';
|
|
return = "200 '{\"m.server\": \"${cfg.matrixDomain}:443\"}'";
|
|
};
|
|
};
|
|
};
|
|
|
|
security.acme = {
|
|
acceptTerms = true;
|
|
defaults = {
|
|
email = "hectic.yukkop.it@gmail.com";
|
|
enableDebugLogs = true;
|
|
};
|
|
};
|
|
systemd.services.matrix-synapse-users = lib.mkIf (matrixUsers != []) {
|
|
description = "Provision Matrix Synapse users";
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [ config.services.matrix-synapse.serviceUnit ];
|
|
requires = [ config.services.matrix-synapse.serviceUnit ];
|
|
path = with pkgs; [ curl coreutils gawk ];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
User = "matrix-synapse";
|
|
};
|
|
script = ''
|
|
until curl -sf http://127.0.0.1:8008/_matrix/client/versions >/dev/null; do
|
|
sleep 2
|
|
done
|
|
|
|
REGISTRATION_SHARED_SECRET="$(awk -F': *' '$1 == "registration_shared_secret" { print $2; exit }' "${cfg.secretsFile}")"
|
|
|
|
if [ -z "$REGISTRATION_SHARED_SECRET" ]; then
|
|
printf 'registration_shared_secret not found in %s\n' '${cfg.secretsFile}' >&2
|
|
exit 1
|
|
fi
|
|
|
|
${builtins.concatStringsSep "\n" (map mkUserRegistration matrixUsers)}
|
|
'';
|
|
};
|
|
};
|
|
}
|