227 lines
6.3 KiB
Nix
227 lines
6.3 KiB
Nix
{ pkgs, lib, config, ... }:
|
|
let
|
|
hostname = "matrix";
|
|
fqdn = "${hostname}.cloonar.com";
|
|
baseUrl = "https://${fqdn}";
|
|
clientConfig."m.homeserver".base_url = baseUrl;
|
|
serverConfig."m.server" = "${fqdn}:443";
|
|
mkWellKnown = data: ''
|
|
default_type application/json;
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 200 '${builtins.toJSON data}';
|
|
'';
|
|
in {
|
|
# Secrets for Synapse
|
|
sops.secrets.synapse-oidc-client-secret = {
|
|
owner = "matrix-synapse";
|
|
};
|
|
sops.secrets.mautrix-whatsapp-env = { };
|
|
sops.secrets.mautrix-signal-env = { };
|
|
sops.secrets.mautrix-discord-env = { };
|
|
|
|
# PostgreSQL database for Synapse
|
|
services.postgresql = {
|
|
enable = true;
|
|
# Synapse requires C locale for correct collation behavior
|
|
initdbArgs = [ "--lc-collate=C" "--lc-ctype=C" ];
|
|
ensureDatabases = [ "matrix-synapse" ];
|
|
ensureUsers = [
|
|
{
|
|
name = "matrix-synapse";
|
|
ensureDBOwnership = true;
|
|
}
|
|
];
|
|
};
|
|
|
|
services.postgresqlBackup.enable = true;
|
|
services.postgresqlBackup.databases = [ "matrix-synapse" ];
|
|
|
|
# Synapse homeserver
|
|
services.matrix-synapse = {
|
|
enable = true;
|
|
settings = {
|
|
server_name = "cloonar.com";
|
|
public_baseurl = baseUrl;
|
|
|
|
listeners = [
|
|
{
|
|
port = 8008;
|
|
bind_addresses = [ "::1" ];
|
|
type = "http";
|
|
tls = false;
|
|
x_forwarded = true;
|
|
resources = [
|
|
{
|
|
compress = true;
|
|
names = [ "client" "federation" ];
|
|
}
|
|
];
|
|
}
|
|
];
|
|
|
|
database = {
|
|
name = "psycopg2";
|
|
args = {
|
|
host = "/run/postgresql";
|
|
database = "matrix-synapse";
|
|
user = "matrix-synapse";
|
|
};
|
|
};
|
|
|
|
# Disable registration - users created via OIDC
|
|
enable_registration = false;
|
|
allow_guest_access = false;
|
|
|
|
# OIDC SSO via Authelia
|
|
oidc_providers = [
|
|
{
|
|
idp_id = "authelia";
|
|
idp_name = "Authelia";
|
|
discover = true;
|
|
issuer = "https://auth.cloonar.com";
|
|
user_profile_method = "userinfo_endpoint";
|
|
client_id = "synapse";
|
|
client_secret_path = config.sops.secrets.synapse-oidc-client-secret.path;
|
|
scopes = [ "openid" "profile" "email" ];
|
|
allow_existing_users = true;
|
|
user_mapping_provider.config = {
|
|
subject_claim = "sub";
|
|
localpart_template = "{{ user.email | localpart_from_email }}";
|
|
display_name_template = "{{ user.name }}";
|
|
email_template = "{{ user.email }}";
|
|
};
|
|
}
|
|
];
|
|
|
|
};
|
|
};
|
|
|
|
# Synapse runs inside an isolated microVM, so PrivateUsers provides minimal
|
|
# additional security. Disabling it allows Synapse to read bridge registration
|
|
# files via SupplementaryGroups (user namespace blocks mapped GIDs otherwise).
|
|
systemd.services.matrix-synapse.serviceConfig.PrivateUsers = lib.mkForce false;
|
|
|
|
# Element Web client
|
|
services.nginx.virtualHosts."element.cloonar.com" = {
|
|
forceSSL = true;
|
|
enableACME = true;
|
|
acmeRoot = null;
|
|
root = pkgs.element-web.override {
|
|
conf = {
|
|
default_theme = "dark";
|
|
default_server_config = {
|
|
"m.homeserver" = {
|
|
base_url = "https://matrix.cloonar.com";
|
|
server_name = "cloonar.com";
|
|
};
|
|
};
|
|
disable_custom_urls = true;
|
|
disable_3pid_login = true;
|
|
default_country_code = "AT";
|
|
};
|
|
};
|
|
};
|
|
|
|
# Synapse nginx reverse proxy
|
|
services.nginx.virtualHosts."${fqdn}" = {
|
|
forceSSL = true;
|
|
enableACME = true;
|
|
acmeRoot = null;
|
|
locations."/".extraConfig = ''
|
|
return 404;
|
|
'';
|
|
locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
|
|
locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
|
|
locations."/_matrix".proxyPass = "http://[::1]:8008";
|
|
locations."/_synapse/client".proxyPass = "http://[::1]:8008";
|
|
};
|
|
|
|
#
|
|
# Mautrix bridges (using NixOS modules)
|
|
# Modules handle users, groups, registration files, Synapse integration,
|
|
# and service ordering automatically via registerToSynapse.
|
|
#
|
|
|
|
# WhatsApp bridge
|
|
services.mautrix-whatsapp = {
|
|
enable = true;
|
|
registerToSynapse = true;
|
|
environmentFile = config.sops.secrets.mautrix-whatsapp-env.path;
|
|
settings = {
|
|
homeserver = {
|
|
address = "http://[::1]:8008";
|
|
domain = "cloonar.com";
|
|
};
|
|
bridge = {
|
|
command_prefix = "!wa";
|
|
permissions."*" = "relay";
|
|
permissions."cloonar.com" = "user";
|
|
relay.enabled = true;
|
|
};
|
|
encryption = {
|
|
allow = true;
|
|
default = true;
|
|
require = true;
|
|
pickle_key = "$MAUTRIX_WHATSAPP_PICKLE_KEY";
|
|
};
|
|
};
|
|
};
|
|
|
|
# Signal bridge
|
|
services.mautrix-signal = {
|
|
enable = true;
|
|
registerToSynapse = true;
|
|
environmentFile = config.sops.secrets.mautrix-signal-env.path;
|
|
settings = {
|
|
homeserver = {
|
|
address = "http://[::1]:8008";
|
|
domain = "cloonar.com";
|
|
};
|
|
bridge = {
|
|
command_prefix = "!signal";
|
|
permissions."*" = "relay";
|
|
permissions."cloonar.com" = "user";
|
|
relay.enabled = true;
|
|
};
|
|
encryption = {
|
|
allow = true;
|
|
default = true;
|
|
require = true;
|
|
pickle_key = "$MAUTRIX_SIGNAL_PICKLE_KEY";
|
|
};
|
|
matrix.sync_direct_chat_list = true;
|
|
};
|
|
};
|
|
|
|
# Discord bridge
|
|
services.mautrix-discord = {
|
|
enable = true;
|
|
registerToSynapse = true;
|
|
environmentFile = config.sops.secrets.mautrix-discord-env.path;
|
|
settings = {
|
|
homeserver = {
|
|
address = "http://[::1]:8008";
|
|
domain = "cloonar.com";
|
|
};
|
|
bridge = {
|
|
command_prefix = "!discord";
|
|
permissions."*" = "relay";
|
|
permissions."cloonar.com" = "user";
|
|
relay.enabled = true;
|
|
};
|
|
# Override dummy token defaults so env var substitution writes real tokens
|
|
# into the config and registration file (module defaults are placeholder strings)
|
|
appservice = {
|
|
as_token = "$MAUTRIX_DISCORD_AS_TOKEN";
|
|
hs_token = "$MAUTRIX_DISCORD_HS_TOKEN";
|
|
};
|
|
encryption = {
|
|
allow = true;
|
|
default = true;
|
|
require = true;
|
|
pickle_key = "$MAUTRIX_DISCORD_PICKLE_KEY";
|
|
};
|
|
};
|
|
};
|
|
|
|
}
|