# NixOps configuration for the hosts running a Matrix server (synapse) { config, pkgs, lib, ... }: { imports = [ ../secrets/matrix.nix ]; i18n = { extraLocaleSettings = { LC_COLLATE = "C"; # Ensure correct locale for postgres LC_CTYPE = "C"; # Ensure correct locale for postgres }; }; services = { matrix-synapse = { enable = true; # Enable the synapse server server_name = "mcwhirter.io"; # Server's public domain name public_baseurl = "https://synapse.mcwhirter.io:443/"; # Matrix target URL enable_registration = true; # Toggle user registration listeners = [ { # federation bind_address = ""; port = 8448; resources = [ { compress = true; names = [ "client" ]; } { compress = false; names = [ "federation" ]; } ]; tls = true; type = "http"; x_forwarded = false; } { # client bind_address = "::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 tls_certificate_path = "/var/lib/acme/mcwhirter.io/fullchain.pem"; tls_private_key_path = "/var/lib/acme/mcwhirter.io/key.pem"; turn_shared_secret = "IZI43ylg6aJdMwy5MyhUPqT8SJD4C3P1vDcIFMzqGvTXJiCjAEvnPcDCBZfig5Q6"; 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; extraConfig = '' enable_group_creation: true # Allow users to create communities ''; }; 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 ensurePermissions = { # Ensure the database permissions persist "DATABASE \"matrix-synapse\"" = "ALL PRIVILEGES"; "ALL TABLES IN SCHEMA public" = "ALL PRIVILEGES"; }; } ]; # 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" LC_CTYPE = "C"; ''; }; }; 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 }