matrix: moved to own dir + added housecleaning
This commit is contained in:
parent
5aea8b7afb
commit
5bdebc357a
5 changed files with 52 additions and 2 deletions
7
machines/gerd/services/matrix/default.nix
Normal file
7
machines/gerd/services/matrix/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./matrix-synapse.nix
|
||||
./element.nix
|
||||
./housecleaning.nix
|
||||
];
|
||||
}
|
42
machines/gerd/services/matrix/element.nix
Normal file
42
machines/gerd/services/matrix/element.nix
Normal file
|
@ -0,0 +1,42 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
svc_domain = "chat.${config.mine.shared.settings.domain}";
|
||||
|
||||
# configure element web client
|
||||
pkg_element = pkgs.element-web.override {
|
||||
conf = {
|
||||
default_server_name = config.mine.shared.settings.domain;
|
||||
embedded_pages.login_for_welcome = true;
|
||||
disable_guests = true;
|
||||
|
||||
brand = config.mine.shared.settings.brand;
|
||||
default_theme = "dark";
|
||||
|
||||
features = {
|
||||
feature_latex_maths = true;
|
||||
feature_video_rooms = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
services.nginx.virtualHosts."${svc_domain}" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/".root = pkg_element;
|
||||
};
|
||||
|
||||
mine.shared.meta.element = {
|
||||
name = "Element";
|
||||
description = "We host our own Element instance, get on it and start chatting!";
|
||||
url = "https://${svc_domain}";
|
||||
|
||||
package = let
|
||||
pkg = pkg_element;
|
||||
in {
|
||||
name = pkg.pname;
|
||||
version = pkg.version;
|
||||
meta = pkg.meta;
|
||||
};
|
||||
};
|
||||
}
|
38
machines/gerd/services/matrix/housecleaning.nix
Normal file
38
machines/gerd/services/matrix/housecleaning.nix
Normal file
|
@ -0,0 +1,38 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
# delete empty directories
|
||||
# - https://github.com/element-hq/synapse/issues/7690
|
||||
# - https://github.com/matrix-org/synapse/issues/7690
|
||||
systemd.services.matrix-synapse.preStart =
|
||||
''${pkgs.findutils}/bin/find ${config.services.matrix-synapse.dataDir}/media_store -empty -type d -delete'';
|
||||
|
||||
systemd.timers."matrix-synapse-housecleaning-empty-dirs" = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "Mon *-*-* 04:00:00";
|
||||
Unit = config.systemd.services.matrix-synapse.name;
|
||||
};
|
||||
};
|
||||
|
||||
# vacuum database
|
||||
systemd.services."matrix-synapse-psql-vacuum" = let
|
||||
psqlUser = config.systemd.services.postgresql.serviceConfig.user;
|
||||
dbName = config.services.matrix-synapse.settings.database.args.database;
|
||||
in {
|
||||
serviceConfig = {
|
||||
User = psqlUser;
|
||||
ExecStart = pkgs.writeScript "matrix-synapse-psql-vacuum.sh" ''
|
||||
${config.services.postgresql.package}/bin/psql -d ${dbName} -c "vacuum full"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers."matrix-synapse-housecleaning-vacuum-db" = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "Mon *-*-* 04:00:00";
|
||||
Unit = config.systemd.services.matrix-synapse-psql-vacuum.name;
|
||||
};
|
||||
};
|
||||
}
|
205
machines/gerd/services/matrix/matrix-synapse.nix
Normal file
205
machines/gerd/services/matrix/matrix-synapse.nix
Normal file
|
@ -0,0 +1,205 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
svc_domain = "matrix.${config.mine.shared.settings.domain}";
|
||||
|
||||
max_upload_size = "50M";
|
||||
|
||||
name = "matrix-synapse";
|
||||
|
||||
matrix_synapse_user = name;
|
||||
matrix_synapse_group = name;
|
||||
|
||||
oidcConfigPath = "/run/${name}/oidc.yaml";
|
||||
|
||||
stateDir = config.mine.zfsMounts."rpool/safe/svcs/synapse";
|
||||
matrix_port = 8448;
|
||||
in {
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
dataDir = stateDir;
|
||||
|
||||
extras = [ "oidc" ];
|
||||
|
||||
extraConfigFiles = [
|
||||
oidcConfigPath
|
||||
];
|
||||
|
||||
settings = {
|
||||
server_name = config.mine.shared.settings.domain;
|
||||
public_baseurl = "https://${svc_domain}";
|
||||
|
||||
enable_registration = false;
|
||||
password_config.enabled = false;
|
||||
|
||||
listeners = [
|
||||
{
|
||||
port = matrix_port;
|
||||
bind_addresses = [ "localhost" ];
|
||||
x_forwarded = true;
|
||||
tls = false;
|
||||
resources = [{
|
||||
names = [ "federation" "client" ];
|
||||
compress = false;
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
# database
|
||||
# shut up shut up shut up shut up!!!
|
||||
database.allow_unsafe_locale = true;
|
||||
database_type = "psycopg2";
|
||||
database_args.database = "matrix-synapse";
|
||||
|
||||
# increase max_upload_size, otherwise might not
|
||||
# be able to watch cat videos
|
||||
max_upload_size = max_upload_size;
|
||||
|
||||
# only authenticated media
|
||||
enable_authenticated_media = true;
|
||||
|
||||
# retentien policies
|
||||
media_retention = {
|
||||
local_media_lifetime = "90d";
|
||||
remote_media_lifetime = "14d";
|
||||
};
|
||||
|
||||
# keep messages MIN 1 day, MAX 1 year
|
||||
retention = {
|
||||
enabled = true;
|
||||
default_policy = {
|
||||
min_lifetime = "1d";
|
||||
max_lifetime = "1y";
|
||||
};
|
||||
allowed_lifetime_min = "1d";
|
||||
allowed_lifetime_max = "1y";
|
||||
};
|
||||
|
||||
|
||||
# automatically forget room on leave/kick/ban, and
|
||||
# purge from db after X time
|
||||
forget_rooms_on_leave = true;
|
||||
forgotten_room_retention_period = "28d";
|
||||
};
|
||||
};
|
||||
|
||||
# setup OIDC/OpenID/OAUTH2/whatever for synapse
|
||||
# do this way, instead of having EVERYTHING in a secret file.
|
||||
systemd.services.matrix-synapse = {
|
||||
# https://linux-audit.com/systemd/systemd-syscall-filtering/
|
||||
# https://github.com/restic/rest-server/pull/249
|
||||
# https://github.com/golang/go/issues/46279
|
||||
serviceConfig.SystemCallFilter = [ "setrlimit" ];
|
||||
serviceConfig.EnvironmentFile = config.age.secrets.matrix-synapse-config-authelia-secret.path;
|
||||
preStart = let
|
||||
oidc_config = (pkgs.formats.yaml {}).generate "matrix-synapse-oidc-config" {
|
||||
oidc_providers = [{
|
||||
idp_id = "authelia";
|
||||
idp_name = "Authelia";
|
||||
idp_icon = "mxc://authelia.com/cKlrTPsGvlpKxAYeHWJsdVHI";
|
||||
client_id = "synapse";
|
||||
client_secret = "$CLIENT_SECRET";
|
||||
issuer = "https://${config.mine.shared.settings.authelia.domain}";
|
||||
discover = true;
|
||||
|
||||
scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
|
||||
user_mapping_provider.config = {
|
||||
subject_claim = "sub";
|
||||
localpart_template = "{{ user.preferred_username }}";
|
||||
display_name_template = "{{ user.name }}";
|
||||
email_template = "{{ user.email }}";
|
||||
};
|
||||
}];
|
||||
};
|
||||
in ''
|
||||
${pkgs.envsubst}/bin/envsubst \
|
||||
-o ${oidcConfigPath} \
|
||||
-i ${oidc_config}
|
||||
'';
|
||||
};
|
||||
|
||||
# setup for oidc
|
||||
services.authelia.instances.main.settings.identity_providers.oidc.clients = [{
|
||||
client_id = "synapse";
|
||||
client_name = "Synapse";
|
||||
client_secret = "$pbkdf2-sha512$310000$SmE9y.LA9lnzxNWL6CeWQA$zcrum.Rst9xQy/MKBI5i.UiUdSjx/F0ak65Z3vYk0w7/GMWIqXaW3GnE7bJQw6nHi5eZ2uhKHtW/DKp2TDVhbQ";
|
||||
redirect_uris = [ "https://${svc_domain}/_synapse/client/oidc/callback" ];
|
||||
scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
}];
|
||||
|
||||
# ensure databases + user is setup
|
||||
services.postgresql = {
|
||||
ensureDatabases = [ matrix_synapse_user ];
|
||||
ensureUsers = [{
|
||||
name = matrix_synapse_user;
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
virtualHosts."${svc_domain}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
# only proxy `_matrix` and `_synapse/client`, it is not ideal to proxy `_synapse/admin`
|
||||
locations."~ ^(/_matrix|/_synapse/client)" = {
|
||||
proxyPass = "http://localhost:${builtins.toString matrix_port}";
|
||||
|
||||
extraConfig = "client_max_body_size ${max_upload_size};";
|
||||
};
|
||||
};
|
||||
|
||||
# serve `.well-known/matrix/{server,client}` because matrix synapse runs on subdomain
|
||||
virtualHosts."${config.mine.shared.settings.domain}" = let
|
||||
client = {
|
||||
"m.homeserver" = { "base_url" = "https://${svc_domain}"; };
|
||||
"m.identity_server" = { "base_url" = "https://matrix.org"; };
|
||||
};
|
||||
server = { "m.server" = "${svc_domain}:443"; };
|
||||
in {
|
||||
locations."/.well-known/matrix/server".extraConfig = ''
|
||||
add_header Content-Type application/json;
|
||||
return 200 '${builtins.toJSON server}';
|
||||
'';
|
||||
|
||||
locations."/.well-known/matrix/client".extraConfig = ''
|
||||
add_header Content-Type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '${builtins.toJSON client}';
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"Z ${stateDir} 0770 ${matrix_synapse_user} ${matrix_synapse_group} -"
|
||||
];
|
||||
|
||||
age.secrets = {
|
||||
matrix-synapse-config-authelia-secret.owner = matrix_synapse_user;
|
||||
};
|
||||
|
||||
mine.shared.settings.matrix-synapse.domain = svc_domain;
|
||||
|
||||
mine.shared.meta.matrix-synapse = {
|
||||
name = "Matrix Synapse";
|
||||
description = "We host our own Matrix homeserver using Synapse! Login using your favourite which supports OpenID.";
|
||||
url = "https://${svc_domain}";
|
||||
|
||||
package = let
|
||||
pkg = pkgs.matrix-synapse-unwrapped;
|
||||
in {
|
||||
name = pkg.pname;
|
||||
version = pkg.version;
|
||||
meta = pkg.meta;
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue