# NixOps configuration for the hosts running a Matrix server (synapse) { config, pkgs, lib, ... }: { i18n = { extraLocaleSettings = { LC_COLLATE = "C.UTF-8"; # Ensure correct locale for postgres LC_CTYPE = "C.UTF-8"; # Ensure correct locale for postgres }; }; services = { matrix-synapse = { enable = true; # Enable the synapse server settings = { enable_registration = false; # Toggle user registration enable_registration_without_verification = false; extraConfig = '' enable_group_creation: true # Allow users to create communities ''; listeners = [ { # federation bind_addresses = []; port = 8448; resources = [ { compress = true; names = ["client"]; } { compress = false; names = ["federation"]; } ]; tls = true; type = "http"; x_forwarded = false; } { # client bind_addresses = ["::1"]; # Listen on localhost only port = 8008; # Port to listen on resources = [ { compress = true; names = ["client"]; } { compress = false; names = ["federation"]; } ]; tls = true; type = "http"; x_forwarded = true; } ]; max_upload_size = "200M"; # Also set client_max_body_size to at least this public_baseurl = "https://synapse.mcwhirter.io:443/"; # Matrix target URL server_name = "mcwhirter.io"; # Server's public domain name tls_certificate_path = "/var/lib/acme/mcwhirter.io/fullchain.pem"; tls_private_key_path = "/var/lib/acme/mcwhirter.io/key.pem"; turn_shared_secret = config.services.coturn.static-auth-secret; turn_uris = [ "turn:turn.mcwhirter.io:5349?transport=udp" "turn:turn.mcwhirter.io:5350?transport=udp" "turn:turn.mcwhirter.io:5349?transport=tcp" "turn:turn.mcwhirter.io:5350?transport=tcp" ]; url_preview_enabled = true; }; }; nginx = { enable = true; recommendedTlsSettings = true; recommendedOptimisation = true; recommendedGzipSettings = true; recommendedProxySettings = true; virtualHosts = { "synapse.mcwhirter.io" = { forceSSL = true; enableACME = true; locations = { "/_matrix" = {proxyPass = "https://[::1]:8008";}; "/.well-known/matrix/server".extraConfig = let # use 443 instead of the default 8448 port to unite # the client-server and server-server port for simplicity server = {"m.server" = "synapse.mcwhirter.io:443";}; in '' add_header Content-Type application/json; return 200 '${builtins.toJSON server}'; ''; "= /.well-known/matrix/client".extraConfig = let client = { "m.homeserver" = { "base_url" = "https://synapse.mcwhirter.io"; }; "m.identity_server" = {"base_url" = "https://vector.im";}; }; # ACAO required to allow element-web on any URL to request this json file in '' add_header Content-Type application/json; add_header Access-Control-Allow-Origin *; return 200 '${builtins.toJSON client}'; ''; }; extraConfig = '' client_max_body_size 200M; # Needs to be no less than max_upload_size ''; }; "chat.mcwhirter.io" = { forceSSL = true; enableACME = true; root = pkgs.element-web; # Install RIOT web in the nginx root }; }; }; postgresql = { enable = true; ensureDatabases = ["matrix-synapse"]; # Ensure the database persists ensureUsers = [ { name = "matrix-synapse"; # Ensure the database user persists ensureDBOwnership = true; } ]; # Initial database creation initialScript = pkgs.writeText "synapse-init.sql" '' CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse'; CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" TEMPLATE template0 LC_COLLATE = "C.UTF-8" LC_CTYPE = "C.UTF-8"; ''; }; }; services.postgresqlBackup = { enable = true; compression = "zstd"; }; services.postgresqlBackup.databases = ["matrix-synapse"]; security.acme = { acceptTerms = true; certs = { "chat.mcwhirter.io" = { postRun = "systemctl reload nginx.service"; email = "acme@mcwhirter.io"; }; "synapse.mcwhirter.io" = { group = "matrix-synapse"; postRun = "systemctl reload nginx.service; systemctl restart matrix-synapse.service"; email = "acme@mcwhirter.io"; }; }; }; networking.firewall = { enable = true; allowedTCPPorts = [ 443 # HTTPS 8448 # Matrix federation ]; }; users.groups.matrix-synapse.members = ["nginx"]; # Added for keys permissions }