From a32a2800f726df95dfababd547cc070cab287407 Mon Sep 17 00:00:00 2001 From: DerGrumpf Date: Wed, 6 May 2026 23:45:13 +0200 Subject: [PATCH] Matrix Stack working! --- nixos/roles/keycloack.nix | 28 ++++++++++ nixos/roles/matrix/coturn.nix | 95 ++++++++++++++++++++++++++++++++++ nixos/roles/matrix/default.nix | 5 +- nixos/roles/matrix/livekit.nix | 63 ++++------------------ nixos/roles/matrix/maubot.nix | 22 ++++++++ nixos/roles/matrix/mjolnir.nix | 17 ++++++ nixos/roles/matrix/synapse.nix | 34 ++++++++++-- secrets/secrets.yaml | 8 +-- 8 files changed, 210 insertions(+), 62 deletions(-) create mode 100644 nixos/roles/keycloack.nix create mode 100644 nixos/roles/matrix/coturn.nix create mode 100644 nixos/roles/matrix/maubot.nix create mode 100644 nixos/roles/matrix/mjolnir.nix diff --git a/nixos/roles/keycloack.nix b/nixos/roles/keycloack.nix new file mode 100644 index 0000000..0d7f491 --- /dev/null +++ b/nixos/roles/keycloack.nix @@ -0,0 +1,28 @@ +{ config, ... }: +{ + services = { + nginx.virtualHosts."www.cyperpunk.de".locations."/cloak" = { + proxyPass = "http://localhost:${toString config.services.keycloak.settings.http-port}/cloak/"; + }; + + keycloak = { + enable = true; + + database = { + type = "postgresql"; + createLocally = true; + + username = "keycloak"; + passwordFile = "/etc/nixos/secrets/keycloak_psql_pass"; + }; + + settings = { + hostname = "cyperpunk.de"; + http-relative-path = "/cloak"; + http-port = 38080; + proxy = "passthrough"; + http-enabled = true; + }; + }; + }; +} diff --git a/nixos/roles/matrix/coturn.nix b/nixos/roles/matrix/coturn.nix new file mode 100644 index 0000000..8c630ad --- /dev/null +++ b/nixos/roles/matrix/coturn.nix @@ -0,0 +1,95 @@ +{ config, lib, ... }: +{ + sops.secrets = { + coturn_static_auth_secret = { + owner = "turnserver"; + group = "turnserver"; + }; + + coturn_static_auth_secret_synapse = { + owner = "matrix-synapse"; + group = "matrix-synapse"; + key = "coturn_static_auth_secret"; + }; + }; + + services = { + coturn = rec { + enable = true; + no-cli = true; + no-tcp-relay = true; + min-port = 49000; + max-port = 50000; + use-auth-secret = true; + static-auth-secret-file = config.sops.secrets.coturn_static_auth_secret.path; + realm = "turn.cyperpunk.de"; + cert = "${config.security.acme.certs.${realm}.directory}/full.pem"; + pkey = "${config.security.acme.certs.${realm}.directory}/key.pem"; + extraConfig = '' + no-multicast-peers + denied-peer-ip=0.0.0.0-0.255.255.255 + denied-peer-ip=10.0.0.0-10.255.255.255 + denied-peer-ip=100.64.0.0-100.127.255.255 + denied-peer-ip=127.0.0.0-127.255.255.255 + denied-peer-ip=169.254.0.0-169.254.255.255 + denied-peer-ip=172.16.0.0-172.31.255.255 + denied-peer-ip=192.0.0.0-192.0.0.255 + denied-peer-ip=192.0.2.0-192.0.2.255 + denied-peer-ip=192.88.99.0-192.88.99.255 + denied-peer-ip=192.168.0.0-192.168.255.255 + denied-peer-ip=198.18.0.0-198.19.255.255 + denied-peer-ip=198.51.100.0-198.51.100.255 + denied-peer-ip=203.0.113.0-203.0.113.255 + denied-peer-ip=240.0.0.0-255.255.255.255 + denied-peer-ip=::1 + denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff + denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255 + denied-peer-ip=100::-100::ffff:ffff:ffff:ffff + denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff + denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff + denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff + denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff + ''; + relay-ips = [ "178.254.8.35" ]; + }; + + nginx.virtualHosts."turn.cyperpunk.de" = { + forceSSL = true; + enableACME = true; + }; + + matrix-synapse.settings = with config.services.coturn; { + turn_uris = [ + "turn:${realm}:3478?transport=udp" + "turn:${realm}:3478?transport=tcp" + ]; + turn_shared_secret_path = config.sops.secrets.coturn_static_auth_secret_synapse.path; + turn_user_lifetime = "1h"; + }; + }; + + security.acme.certs."turn.cyperpunk.de".group = "nginx"; + + users.users.turnserver.extraGroups = [ "nginx" ]; + + networking.firewall.interfaces.ens3 = + let + range = + with config.services.coturn; + lib.singleton { + from = min-port; + to = max-port; + }; + in + { + allowedUDPPortRanges = range; + allowedUDPPorts = [ + 3478 + 5349 + ]; + allowedTCPPorts = [ + 3478 + 5349 + ]; + }; +} diff --git a/nixos/roles/matrix/default.nix b/nixos/roles/matrix/default.nix index b9b7641..1b05d03 100644 --- a/nixos/roles/matrix/default.nix +++ b/nixos/roles/matrix/default.nix @@ -5,7 +5,10 @@ imports = [ ./synapse.nix #./lk-jwt.nix - #./livekit.nix + ./livekit.nix ./clients.nix + ./mjolnir.nix + ./coturn.nix + #./maubot.nix # known security risk ]; } diff --git a/nixos/roles/matrix/livekit.nix b/nixos/roles/matrix/livekit.nix index d5d2752..9460a95 100644 --- a/nixos/roles/matrix/livekit.nix +++ b/nixos/roles/matrix/livekit.nix @@ -1,64 +1,19 @@ -{ config, lib, ... }: +{ config, ... }: { - # Shared key file — same secret used by lk-jwt-service (see lk-jwt.nix) - sops.secrets.livekit_key = { }; + sops.secrets.livekit_key_file = { }; services.livekit = { enable = true; openFirewall = true; - keyFile = config.sops.secrets.livekit_key.path; - settings = { - rtc = { - tcp_port = 7881; - port_range_start = 50000; - port_range_end = 60000; - use_external_ip = true; - node_ip = "178.254.8.35"; - }; - room = { - # Must be false — rooms are created by the JWT service on demand - auto_create = false; - enabled_codecs = [ - { mime = "video/VP8"; } - { mime = "video/VP9"; } - { mime = "video/H264"; } - { mime = "audio/opus"; } - ]; - enable_remote_unmute = true; - }; - }; + settings.room.auto_create = false; + keyFile = config.sops.secrets.livekit_key_file.path; }; - networking.firewall = { - allowedTCPPorts = [ 7881 ]; - # WebRTC media relay — must be open or calls connect then immediately drop - allowedUDPPortRanges = [ - { - from = 50000; - to = 60000; - } - ]; + services.lk-jwt-service = { + enable = true; + livekitUrl = "wss://cyperpunk.de/livekit/sfu"; + keyFile = config.sops.secrets.livekit_key_file.path; }; - systemd.services.livekit.serviceConfig = { - PrivateUsers = lib.mkForce false; - DynamicUser = lib.mkForce false; - User = "livekit"; - Group = "livekit"; - RestrictAddressFamilies = lib.mkForce [ - "AF_INET" - "AF_INET6" - "AF_NETLINK" - "AF_UNIX" - ]; - SystemCallFilter = lib.mkForce [ "@system-service" ]; - }; - - users = { - users.livekit = { - isSystemUser = true; - group = "livekit"; - }; - groups.livekit = { }; - }; + systemd.services.lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = "cyperpunk.de"; } diff --git a/nixos/roles/matrix/maubot.nix b/nixos/roles/matrix/maubot.nix new file mode 100644 index 0000000..1f25337 --- /dev/null +++ b/nixos/roles/matrix/maubot.nix @@ -0,0 +1,22 @@ +{ config, ... }: +{ + services = { + maubot = { + enable = true; + settings = { + database = "postgresql://maubot@localhost/maubot"; + server = { + public_url = "matrix.cyperpunk.de"; + #ui_base_path = "/another/base/path"; + }; + }; + }; + + nginx.virtualHosts."matrix.cyperpunk.de".locations = { + "/_matrix/maubot/" = { + proxyPass = "http://127.0.0.1:${toString config.services.maubot.settings.server.port}"; + proxyWebsockets = true; + }; + }; + }; +} diff --git a/nixos/roles/matrix/mjolnir.nix b/nixos/roles/matrix/mjolnir.nix new file mode 100644 index 0000000..ff96a2c --- /dev/null +++ b/nixos/roles/matrix/mjolnir.nix @@ -0,0 +1,17 @@ +{ config, ... }: +{ + sops.secrets.mjolnir_access_token = { }; + + services.draupnir = { + enable = true; + secrets.accessToken = config.sops.secrets.mjolnir_access_token.path; + settings = { + homeserverUrl = "https://matrix.cyperpunk.de"; + managementRoom = "!eErCimyDjLSebHjpJA:cyperpunk.de"; + }; + }; +} + +#curl -X POST https://matrix.cyperpunk.de/_matrix/client/v3/login \ +# -H "Content-Type: application/json" \ +# -d '{"type":"m.login.password ","user":"mjolnir","password":"i318HXBRkt)Lh$nOPwq#6n9z&7jV}-uQCE{