Compare commits
10 commits
dc516381d3
...
13ab4ae245
Author | SHA1 | Date | |
---|---|---|---|
|
13ab4ae245 | ||
|
e54d7373d8 | ||
|
0201eed966 | ||
|
4497cbb9c3 | ||
|
7ef927e19c | ||
|
411332ff87 | ||
|
d8fbee7be9 | ||
|
fd2729afc8 | ||
|
84a3027d0c | ||
|
b9163999bb |
10 changed files with 293 additions and 2 deletions
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
./../shared/applications/server/acme.nix
|
./../shared/applications/server/acme.nix
|
||||||
./../shared/applications/server/nginx.nix
|
./../shared/applications/server/nginx.nix
|
||||||
|
./../shared/applications/server/postgresql.nix
|
||||||
|
./../shared/applications/state/postgresql.nix
|
||||||
./../shared/applications/state/ssh.nix
|
./../shared/applications/state/ssh.nix
|
||||||
|
|
||||||
./gerd/services/fricloud-website.nix
|
./gerd/services/fricloud-website.nix
|
||||||
|
@ -17,6 +19,8 @@
|
||||||
./gerd/services/cyberchef.nix
|
./gerd/services/cyberchef.nix
|
||||||
./gerd/services/nextcloud.nix
|
./gerd/services/nextcloud.nix
|
||||||
./gerd/services/stalwart
|
./gerd/services/stalwart
|
||||||
|
|
||||||
|
./gerd/services/matrix-synapse.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = "gerd";
|
networking.hostName = "gerd";
|
||||||
|
@ -31,6 +35,9 @@
|
||||||
"safe/svcs/hedgedoc" = { mountpoint = "/srv/hedgedoc"; extra.options.quota = "5G"; };
|
"safe/svcs/hedgedoc" = { mountpoint = "/srv/hedgedoc"; extra.options.quota = "5G"; };
|
||||||
"safe/svcs/nextcloud" = { mountpoint = "/srv/nextcloud"; extra.options.quota = "5G"; };
|
"safe/svcs/nextcloud" = { mountpoint = "/srv/nextcloud"; extra.options.quota = "5G"; };
|
||||||
"safe/svcs/stalwart" = { mountpoint = "/srv/stalwart"; extra.options.quota = "5G"; };
|
"safe/svcs/stalwart" = { mountpoint = "/srv/stalwart"; extra.options.quota = "5G"; };
|
||||||
|
"safe/svcs/synapse" = { mountpoint = "/srv/synapse"; extra.options.quota = "5G"; };
|
||||||
|
"safe/svcs/postgresql" = { mountpoint = "/srv/postgresql"; extra.options.quota = "5G"; };
|
||||||
|
"backup/postgresql" = { mountpoint = "/media/backup/postgresqlbackup"; extra.options.quota = "5G"; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ let
|
||||||
svc_domain = "hedgedoc.${config.mine.shared.settings.domain}";
|
svc_domain = "hedgedoc.${config.mine.shared.settings.domain}";
|
||||||
|
|
||||||
stateDir = config.mine.zfsMounts."rpool/safe/svcs/hedgedoc";
|
stateDir = config.mine.zfsMounts."rpool/safe/svcs/hedgedoc";
|
||||||
|
|
||||||
|
hedgedoc_user = config.users.users.hedgedoc.name;
|
||||||
in {
|
in {
|
||||||
services.hedgedoc = {
|
services.hedgedoc = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -14,8 +16,11 @@ in {
|
||||||
protocolUseSSL = true;
|
protocolUseSSL = true;
|
||||||
debug = true;
|
debug = true;
|
||||||
uploadsPath = stateDir + "/uploads";
|
uploadsPath = stateDir + "/uploads";
|
||||||
db.dialect = "sqlite";
|
|
||||||
db.storage = stateDir + "/db.sqlite";
|
db = {
|
||||||
|
dialect = "postgresql";
|
||||||
|
host = "/run/postgresql";
|
||||||
|
};
|
||||||
|
|
||||||
# disable annonymous notes, but allow annonymous edits
|
# disable annonymous notes, but allow annonymous edits
|
||||||
allowAnonymous = false;
|
allowAnonymous = false;
|
||||||
|
@ -44,6 +49,15 @@ in {
|
||||||
systemd.services.hedgedoc.serviceConfig.ReadWritePaths = [ stateDir ];
|
systemd.services.hedgedoc.serviceConfig.ReadWritePaths = [ stateDir ];
|
||||||
systemd.services.hedgedoc.serviceConfig.EnvironmentFile = config.age.secrets.lldap-bind-user-pass-hedgedoc-env.path;
|
systemd.services.hedgedoc.serviceConfig.EnvironmentFile = config.age.secrets.lldap-bind-user-pass-hedgedoc-env.path;
|
||||||
|
|
||||||
|
# setup postgresql
|
||||||
|
services.postgresql = {
|
||||||
|
ensureDatabases = [ hedgedoc_user ];
|
||||||
|
ensureUsers = [{
|
||||||
|
name = hedgedoc_user;
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."${svc_domain}" = {
|
services.nginx.virtualHosts."${svc_domain}" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
|
|
198
machines/gerd/services/matrix-synapse.nix
Normal file
198
machines/gerd/services/matrix-synapse.nix
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
{ 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
|
||||||
|
# TODO: Should default to true at some point
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# 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.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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -38,6 +38,19 @@ tmpl_index = """
|
||||||
</pre>
|
</pre>
|
||||||
<hr>
|
<hr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if show_debug %}
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Debug information:
|
||||||
|
<ul>
|
||||||
|
<li>Username: {{ user.username }}</li>
|
||||||
|
<li>Name: {{ user.name }}</li>
|
||||||
|
<li>Email: {{ user.email }}</li>
|
||||||
|
<li>Groups: {{ user.groups }}</li>
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,6 +103,7 @@ def index():
|
||||||
tmpl_index,
|
tmpl_index,
|
||||||
services=services_data,
|
services=services_data,
|
||||||
user=user_info,
|
user=user_info,
|
||||||
|
show_debug=bool(request.args.get("debug")),
|
||||||
)
|
)
|
||||||
return render_template_string(
|
return render_template_string(
|
||||||
tmpl_firstpass,
|
tmpl_firstpass,
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
|
|
||||||
# stalwart
|
# stalwart
|
||||||
stalwart-admin-fallback-password.file = ./stalwart/admin-fallback-password.age;
|
stalwart-admin-fallback-password.file = ./stalwart/admin-fallback-password.age;
|
||||||
|
|
||||||
|
# matrix-synapse
|
||||||
|
matrix-synapse-config-authelia-secret.file = ./matrix-synapse/config-authelia-secret.age;
|
||||||
};
|
};
|
||||||
|
|
||||||
users.groups.secrets-lldap-bind-user-pass = {};
|
users.groups.secrets-lldap-bind-user-pass = {};
|
||||||
|
|
BIN
secrets/matrix-synapse/config-authelia-secret.age
Normal file
BIN
secrets/matrix-synapse/config-authelia-secret.age
Normal file
Binary file not shown.
|
@ -39,4 +39,7 @@ in
|
||||||
|
|
||||||
# mailserver/stalwart
|
# mailserver/stalwart
|
||||||
"stalwart/admin-fallback-password.age".publicKeys = defaultAccess;
|
"stalwart/admin-fallback-password.age".publicKeys = defaultAccess;
|
||||||
|
|
||||||
|
# matrix-synapse
|
||||||
|
"matrix-synapse/config-authelia-secret.age".publicKeys = defaultAccess;
|
||||||
}
|
}
|
||||||
|
|
31
shared/applications/server/postgresql.nix
Normal file
31
shared/applications/server/postgresql.nix
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# backup postgresql databases (everything in ensuredatabases)
|
||||||
|
services.postgresqlBackup = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
compression = "zstd";
|
||||||
|
|
||||||
|
# default to backup all databadatabases
|
||||||
|
databases = config.services.postgresql.ensureDatabases;
|
||||||
|
};
|
||||||
|
|
||||||
|
# default the locale to C. I have NO CLUE why you would
|
||||||
|
# like to use any other locale, than the default C.
|
||||||
|
# However, matrix synapse complains A LOT if it isn't C,
|
||||||
|
# so we just default to it! No worries!
|
||||||
|
# Matrix Synapse Locale Note
|
||||||
|
# - https://github.com/element-hq/synapse/blob/develop/docs/postgres.md#fixing-incorrect-collate-or-ctype
|
||||||
|
# NOTE from postgresql here https://www.postgresql.org/docs/current/locale.html
|
||||||
|
# Using C.UTF-8, because setting `LC_CTYPE=C` will default encoding to SQL_ASCII.
|
||||||
|
# https://pganalyze.com/blog/5mins-postgres-17-builtin-c-utf8-locale
|
||||||
|
systemd.services.postgresql.environment = {
|
||||||
|
LC_CTYPE = "C.UTF-8";
|
||||||
|
LC_COLLATE = "C";
|
||||||
|
};
|
||||||
|
}
|
20
shared/applications/state/postgresql.nix
Normal file
20
shared/applications/state/postgresql.nix
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
stateDir= config.mine.zfsMounts."rpool/safe/svcs/postgresql";
|
||||||
|
backupDir = config.mine.zfsMounts."rpool/backup/postgresql";
|
||||||
|
|
||||||
|
postgresql_user = config.systemd.services.postgresql.serviceConfig.User;
|
||||||
|
postgresql_group = config.systemd.services.postgresql.serviceConfig.Group;
|
||||||
|
in {
|
||||||
|
services.postgresql.dataDir = stateDir;
|
||||||
|
|
||||||
|
# backup postgresql databases (everything in ensuredatabases)
|
||||||
|
services.postgresqlBackup.location = backupDir;
|
||||||
|
|
||||||
|
# ensure correct permissions for postgresql and postgresql backup
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"Z ${stateDir} 0700 ${postgresql_user} ${postgresql_group} -"
|
||||||
|
"Z ${backupDir} 0700 ${postgresql_user} ${postgresql_group} -"
|
||||||
|
];
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ in {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [
|
default = [
|
||||||
"rpool/safe<"
|
"rpool/safe<"
|
||||||
|
"rpool/backup<"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue