From b05354c23bccb541354cedc476198974636a5124 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 21 Jan 2026 15:51:37 +0900 Subject: [PATCH] tsuki/matrix: setup livekit --- hosts/tsuki/services/matrix/default.nix | 6 ++ hosts/tsuki/services/matrix/livekit.nix | 64 ++++++++++++++++++++++ hosts/tsuki/services/matrix/well-known.nix | 62 +++++++++++++++++++++ secrets/tsuki.yaml | 7 ++- 4 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 hosts/tsuki/services/matrix/livekit.nix create mode 100644 hosts/tsuki/services/matrix/well-known.nix diff --git a/hosts/tsuki/services/matrix/default.nix b/hosts/tsuki/services/matrix/default.nix index c0f284f..168a04f 100644 --- a/hosts/tsuki/services/matrix/default.nix +++ b/hosts/tsuki/services/matrix/default.nix @@ -6,6 +6,8 @@ ./postgres.nix ./coturn.nix + ./livekit.nix + ./well-known.nix ]; sops.secrets."matrix_synapse/registration_secret" = { @@ -14,6 +16,10 @@ mode = "0440"; }; + services.matrix-well-known.server."m.server" = "matrix.nani.wtf:443"; + + services.matrix-well-known.client."m.homeserver".base_url = "https://matrix.nani.wtf"; + services.matrix-synapse-next = { enable = true; enableNginx = true; diff --git a/hosts/tsuki/services/matrix/livekit.nix b/hosts/tsuki/services/matrix/livekit.nix new file mode 100644 index 0000000..6b4cf17 --- /dev/null +++ b/hosts/tsuki/services/matrix/livekit.nix @@ -0,0 +1,64 @@ +{ config, lib, fp, ... }: +let + synapseConfig = config.services.matrix-synapse-next; + matrixDomain = "matrix.nani.wtf"; + cfg = config.services.livekit; +in +{ + sops.secrets."matrix/livekit/keyfile/lk-jwt-service" = { }; + sops.templates."matrix-livekit-keyfile" = { + restartUnits = [ + "livekit.service" + "lk-jwt-service.service" + ]; + content = '' + lk-jwt-service: ${config.sops.placeholder."matrix/livekit/keyfile/lk-jwt-service"} + ''; + }; + + services.matrix-well-known.client = lib.mkIf cfg.enable { + "org.matrix.msc4143.rtc_foci" = [{ + type = "livekit"; + livekit_service_url = "https://${matrixDomain}/livekit/jwt"; + }]; + }; + + services.livekit = { + enable = true; + openFirewall = true; + keyFile = config.sops.templates."matrix-livekit-keyfile".path; + + # NOTE: needed for ingress/egress workers + # redis.createLocally = true; + + # settings.room.auto_create = false; + }; + + services.lk-jwt-service = lib.mkIf cfg.enable { + enable = true; + livekitUrl = "wss://${matrixDomain}/livekit/sfu"; + keyFile = config.sops.templates."matrix-livekit-keyfile".path; + }; + + systemd.services.lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = lib.mkIf cfg.enable matrixDomain; + + services.nginx.virtualHosts.${matrixDomain} = lib.mkIf cfg.enable { + locations."^~ /livekit/jwt/" = { + proxyPass = "http://localhost:${toString config.services.lk-jwt-service.port}/"; + }; + + # TODO: load balance to multiple livekit ingress/egress workers + locations."^~ /livekit/sfu/" = { + proxyPass = "http://localhost:${toString config.services.livekit.settings.port}/"; + proxyWebsockets = true; + extraConfig = '' + proxy_send_timeout 120; + proxy_read_timeout 120; + proxy_buffering off; + proxy_set_header Accept-Encoding gzip; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + ''; + }; + }; +} diff --git a/hosts/tsuki/services/matrix/well-known.nix b/hosts/tsuki/services/matrix/well-known.nix new file mode 100644 index 0000000..03e12a8 --- /dev/null +++ b/hosts/tsuki/services/matrix/well-known.nix @@ -0,0 +1,62 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.services.matrix-well-known; + format = pkgs.formats.json { }; + matrixDomain = "matrix.nani.wtf"; +in +{ + options.services.matrix-well-known = { + client = lib.mkOption { + type = lib.types.submodule { freeformType = format.type; }; + default = { }; + example = { + "m.homeserver".base_url = "https://${matrixDomain}/"; + }; + }; + + server = lib.mkOption { + type = lib.types.submodule { freeformType = format.type; }; + default = { }; + example = { + "m.server" = "https://${matrixDomain}/"; + }; + }; + }; + + config = { + services.nginx.virtualHosts.${matrixDomain} = { + locations."= /.well-known/matrix/client" = lib.mkIf (cfg.client != { }) { + alias = format.generate "nginx-well-known-matrix-server.json" cfg.client; + extraConfig = '' + default_type application/json; + add_header Access-Control-Allow-Origin *; + ''; + }; + locations."= /.well-known/matrix/server" = lib.mkIf (cfg.server != { }) { + alias = format.generate "nginx-well-known-matrix-server.json" cfg.server; + extraConfig = '' + default_type application/json; + add_header Access-Control-Allow-Origin *; + ''; + }; + }; + + # TODO: modularize + services.nginx.virtualHosts."nani.wtf" = { + locations."= /.well-known/matrix/client" = lib.mkIf (cfg.client != { }) { + alias = format.generate "nginx-well-known-matrix-server.json" cfg.client; + extraConfig = '' + default_type application/json; + add_header Access-Control-Allow-Origin *; + ''; + }; + locations."= /.well-known/matrix/server" = lib.mkIf (cfg.server != { }) { + alias = format.generate "nginx-well-known-matrix-server.json" cfg.server; + extraConfig = '' + default_type application/json; + add_header Access-Control-Allow-Origin *; + ''; + }; + }; + }; +} diff --git a/secrets/tsuki.yaml b/secrets/tsuki.yaml index f971154..ee18e45 100644 --- a/secrets/tsuki.yaml +++ b/secrets/tsuki.yaml @@ -36,6 +36,9 @@ matrix: id: ENC[AES256_GCM,data:OugWObu794xODuagQTWaX+q60+gbnQfxJK2YEn4QbvS17PUyKPfNg04L9pV9KJvBVRGY3K49M4SNiFdRbMyQbg==,iv:FZaXXBCNjYkO/oECFC8ECt4JQ3VCN+IciFclZs8x0LI=,tag:sbHUvA3cWtoj4RSPAjYzfA==,type:str] hs_token: ENC[AES256_GCM,data:De/ARHF65mJIXZ/N8BmAi0S/F0tC06PkuPATwNm+VzngJCTSxVQnkDZAmqnutQMaHP9ZgJrdCQ7UDCsQhSldEw==,iv:am9m1Fcp1Ale4eH9yknieHL2AinecSrCoqnVPJJqJ1Q=,tag:s8gXMt5CB6W0iuBx6IJ2GQ==,type:str] as_token: ENC[AES256_GCM,data:dT2SesB0kKOdtl8EbSQS7uTX05/cm+6jOAkMlL0liSfttZElTWcA0YXE7X3Xl8hiy5vB0ONS9dA/7RQWKMG1Tw==,iv:icVAE0G1XiQlJpeN9W20MQ3lRDBvnptS5Sj8xiRNa2w=,tag:P8gekOyAhOhfGIUd1fSyKw==,type:str] + livekit: + keyfile: + lk-jwt-service: ENC[AES256_GCM,data:lHhSJCYuvYyAG9tRbReDpe7402x2VTLswlH2mIOm5AtwRnvOpm9/oSA2hA==,iv:eujsO9mK5FtjKG4vmoiQeDV9wjiTBHOp9YQHQbK85NI=,tag:duWhS4VtcYjbkZ0pFR1Gyw==,type:str] matrix_synapse: oauth2_secret: ENC[AES256_GCM,data:Mxzhek6YeRg6lgGvGzrmJz9EakT4sLE5Gw0oyHzF9TjybtjjRmUK4XeEDg8yx2Nt,iv:f656nD6ziJantu7ihmfYvJzxZ1ytvbVS3hezSU75g5A=,tag:G3cwIxcWxLOVAmqmyHDVTg==,type:str] registration_secret: ENC[AES256_GCM,data:Sc5piAESWk9HUe3ZOQ+7ZB9aCZwjTdFrfYkU+XFuXGUZ3xCkCt7QDPmDQBIs+lYOLV9Y165cObKDgMNHBaMkRQ5wXVBrd0l9js70h9LC3IGuK+BOa5tZa4u0zku4zStRuN7xCeGNeAWFOPCQ4a5rQMqbDz6iwWkMQvlHqwzBYtP7PuTuAocwkjlo+3AOnw92DjY4xODPgHR7w4rNSvoSZIUjlAIk3yyHNLV68UiTPoJ5lUqGleLznCpqjLhpxAycfEbWUXCNx8Z5oJ+czptWzhb/hhjH/SgeMvflk8KFwJAYBXxA+YgM+unlWS500OGsgYIbhPyvSzSrs1JkDQBVXA==,iv:/Q4gTEe6WU7XID2ayCFq6xmF6J5UrQw4OjmpU4dhZSA=,tag:kLTdqoanqUAlVrRcKZRxcw==,type:str] @@ -56,8 +59,8 @@ sops: N3ZHc2tWTEpsNFNTVTI5amtPR2RIT3MKUGszZcvd7k+62TPmQNDOFvtjGLegjyQ8 NpCYsXRuIIJ9phzcyG0Iobf3uJBdNtXm2ujBGlY9TqwfIATygwJQjQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-12-29T07:05:51Z" - mac: ENC[AES256_GCM,data:GhhS7iGMiOI1cTJbE8ZAeyKENpvN9L552ajWYfJdSnUFXvH7QXiNBa2LRNccQVX2gnfOTVi16ms+6L+NBHlWMuk+kFywCeR0ZppIt0ktoIfLuzJEyAQHNMNkrdvVAKYd2cjdGRvWhj1qXZERLwl+uSMKj/iK1ghNkBwMNSuzZas=,iv:Jat524mwCqLQCo0u1v4G6kemdjCw2XqghHiQuV38AxA=,tag:6i/hBgTN+wVafrXywuLoUw==,type:str] + lastmodified: "2026-01-21T06:49:14Z" + mac: ENC[AES256_GCM,data:lgvjEFwzcljlLSp6SzVFLibBvUWR91DCgY5B8TPkCYP4/VSYi+13/5RjSsl8FYJvawM3mpKso+JGxBq01nE+U3TQXEcQQWUXo6HoSwVh98LbFmO8ZVi5M9WEQ6wFxMFX22krtIcr3GolCi5vcVh+vNmc10LzxXj8LExRNHZ1ZhA=,iv:fd9bzFHiExcMvBUaz7UPyRYfCr5brjH2NlsaJaFeiDs=,tag:cpO76ahWJWB7jYz96/J+bg==,type:str] pgp: - created_at: "2025-10-24T02:47:54Z" enc: |-