diff options
author | sefidel <contact@sefidel.net> | 2024-01-24 13:29:27 +0900 |
---|---|---|
committer | sefidel <contact@sefidel.net> | 2024-01-24 18:59:54 +0900 |
commit | 8e9b074467006c76768efe04cf1fb1ef9d652c67 (patch) | |
tree | fad73c7f94a74c77714c260d1fc0a63e2d205b49 /modules/services/matrix-bridge | |
download | infra-modules-main.tar.gz infra-modules-main.zip |
Diffstat (limited to 'modules/services/matrix-bridge')
-rw-r--r-- | modules/services/matrix-bridge/_mautrix-discord-module.nix | 205 | ||||
-rw-r--r-- | modules/services/matrix-bridge/_mautrix-signal-module.nix | 204 | ||||
-rw-r--r-- | modules/services/matrix-bridge/default.nix | 390 |
3 files changed, 799 insertions, 0 deletions
diff --git a/modules/services/matrix-bridge/_mautrix-discord-module.nix b/modules/services/matrix-bridge/_mautrix-discord-module.nix new file mode 100644 index 0000000..36cafe6 --- /dev/null +++ b/modules/services/matrix-bridge/_mautrix-discord-module.nix @@ -0,0 +1,205 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + dataDir = "/var/lib/mautrix-discord"; + registrationFile = "${dataDir}/discord-registration.yaml"; + cfg = config.services.mautrix-discord; + settingsFormat = pkgs.formats.json { }; + settingsFile = "${dataDir}/config.json"; + settingsFileUnsubstituted = settingsFormat.generate "mautrix-discord-config.json" cfg.settings; + +in +{ + options = { + services.mautrix-discord = { + enable = mkEnableOption (lib.mdDoc "Mautrix-discord, a Matrix-discord puppeting bridge."); + + package = mkOption { type = types.package; default = pkgs.mautrix-discord; }; + + settings = mkOption rec { + apply = recursiveUpdate default; + inherit (settingsFormat) type; + default = { + homeserver = { + software = "standard"; + }; + + appservice = rec { + database = "sqlite:///${dataDir}/mautrix-discord.db"; + database_opts = { }; + hostname = "localhost"; + port = 8080; + address = "http://localhost:${toString port}"; + }; + + bridge = { + permissions."*" = "relay"; + relay.whitelist = [ ]; + double_puppet_server_map = { }; + login_shared_secret_map = { }; + }; + + logging = { + min_level = "debug"; + writers = [ + { + type = "stdout"; + format = "pretty-colored"; + } + ]; + }; + }; + example = literalExpression '' + { + homeserver = { + address = "http://localhost:8008"; + domain = "public-domain.tld"; + }; + + appservice.public = { + prefix = "/public"; + external = "https://public-appservice-address/public"; + }; + + bridge.permissions = { + "example.com" = "full"; + "@admin:example.com" = "admin"; + }; + } + ''; + description = lib.mdDoc '' + {file}`config.yaml` configuration as a Nix attribute set. + Configuration options should match those described in + [example-config.yaml](https://github.com/mautrix/discord/blob/master/discord/example-config.yaml). + + Secret tokens should be specified using {option}`environmentFile` + instead of this world-readable attribute set. + ''; + }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + description = lib.mdDoc '' + File containing environment variables to be passed to the mautrix-discord service, + in which secret tokens can be specified securely by defining values for e.g. + `MAUTRIX_DISCORD_APPSERVICE_AS_TOKEN`, + `MAUTRIX_DISCORD_APPSERVICE_HS_TOKEN`, + + These environment variables can also be used to set other options by + replacing hierarchy levels by `.`, converting the name to uppercase + and prepending `MAUTRIX_DISCORD_`. + For example, the first value above maps to + {option}`settings.appservice.as_token`. + + The environment variable values can be prefixed with `json::` to have + them be parsed as JSON. For example, `login_shared_secret_map` can be + set as follows: + `MAUTRIX_DISCORD_BRIDGE_LOGIN_SHARED_SECRET_MAP=json::{"example.com":"secret"}`. + ''; + }; + + serviceDependencies = mkOption { + type = with types; listOf str; + default = optional config.services.matrix-synapse.enable "matrix-synapse.service"; + defaultText = literalExpression '' + optional config.services.matrix-synapse.enable "matrix-synapse.service" + ''; + description = lib.mdDoc '' + List of Systemd services to require and wait for when starting the application service. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + users.users.mautrix-discord = { + isSystemUser = true; + group = "mautrix-discord"; + home = dataDir; + description = "Mautrix-Discord bridge user"; + }; + + users.groups.mautrix-discord = {}; + + systemd.services.mautrix-discord = { + description = "Mautrix-discord, a Matrix-discord puppeting bridge."; + + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ] ++ cfg.serviceDependencies; + after = [ "network-online.target" ] ++ cfg.serviceDependencies; + + preStart = '' + # substitute the settings file by environment variables + # in this case read from EnvironmentFile + test -f '${settingsFile}' && rm -f '${settingsFile}' + old_umask=$(umask) + umask 0177 + ${pkgs.envsubst}/bin/envsubst \ + -o '${settingsFile}' \ + -i '${settingsFileUnsubstituted}' \ + umask $old_umask + + # generate the appservice's registration file if absent + if [ ! -f '${registrationFile}' ]; then + ${pkgs.mautrix-discord}/bin/mautrix-discord \ + --generate-registration \ + --config='${settingsFile}' \ + --registration='${registrationFile}' + fi + chmod 640 ${registrationFile} + + umask 0177 + ${pkgs.yq}/bin/yq -s '.[0].appservice.as_token = .[1].as_token + | .[0].appservice.hs_token = .[1].hs_token + | .[0]' '${settingsFile}' '${registrationFile}' \ + > '${settingsFile}.tmp' + mv '${settingsFile}.tmp' '${settingsFile}' + umask $old_umask + ''; + + serviceConfig = { + Type = "simple"; + Restart = "on-failure"; + + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + ProtectSystem = "strict"; + ProtectHome = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + ProtectClock = true; + ProtectHostname = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = ["@system-service"]; + + PrivateTmp = true; + PrivateDevices = true; + PrivateUsers = true; + + User = "mautrix-discord"; + Group = "mautrix-discord"; + WorkingDirectory = dataDir; + StateDirectory = baseNameOf dataDir; + UMask = "0027"; + EnvironmentFile = cfg.environmentFile; + + ExecStart = '' + ${cfg.package}/bin/mautrix-discord \ + --config='${settingsFile}' \ + --registration='${registrationFile}' + ''; + }; + restartTriggers = [settingsFileUnsubstituted]; + }; + }; +} diff --git a/modules/services/matrix-bridge/_mautrix-signal-module.nix b/modules/services/matrix-bridge/_mautrix-signal-module.nix new file mode 100644 index 0000000..983d635 --- /dev/null +++ b/modules/services/matrix-bridge/_mautrix-signal-module.nix @@ -0,0 +1,204 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + dataDir = "/var/lib/mautrix-signal"; + registrationFile = "${dataDir}/signal-registration.yaml"; + cfg = config.services.mautrix-signal; + settingsFormat = pkgs.formats.json { }; + settingsFile = "${dataDir}/config.json"; + settingsFileUnsubstituted = + settingsFormat.generate "mautrix-signal-config.json" cfg.settings; + +in +{ + # NOTE(2024-01-11): Upstream has been moved to a Go version. + # Environment-based credential setting might not work. + options = { + services.mautrix-signal = { + enable = mkEnableOption (lib.mdDoc "Mautrix-Signal, a Matrix-Signal puppeting bridge."); + + package = mkOption { type = types.package; default = pkgs.mautrix-signal; }; + + settings = mkOption rec { + apply = recursiveUpdate default; + inherit (settingsFormat) type; + default = { + homeserver = { + software = "standard"; + }; + + appservice = rec { + database = "sqlite:///${dataDir}/mautrix-signal.db"; + database_opts = { }; + hostname = "localhost"; + port = 8080; + address = "http://localhost:${toString port}"; + }; + + signal.socket_path = config.services.signald.socketPath; + + bridge = { + permissions."*" = "relay"; + relay.whitelist = [ ]; + double_puppet_server_map = { }; + login_shared_secret_map = { }; + }; + + logging = { + min_level = "debug"; + writers = [ + { + type = "stdout"; + format = "pretty-colored"; + } + ]; + }; + }; + example = literalExpression '' + { + homeserver = { + address = "http://localhost:8008"; + domain = "public-domain.tld"; + }; + + appservice.public = { + prefix = "/public"; + external = "https://public-appservice-address/public"; + }; + + bridge.permissions = { + "example.com" = "full"; + "@admin:example.com" = "admin"; + }; + } + ''; + description = lib.mdDoc '' + {file}`config.yaml` configuration as a Nix attribute set. + Configuration options should match those described in + [example-config.yaml](https://github.com/mautrix/signal/blob/master/signal/example-config.yaml). + + Secret tokens should be specified using {option}`environmentFile` + instead of this world-readable attribute set. + ''; + }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + description = lib.mdDoc '' + File containing environment variables to be passed to the mautrix-signal service, + in which secret tokens can be specified securely by defining values for e.g. + `MAUTRIX_SIGNAL_APPSERVICE_AS_TOKEN`, + `MAUTRIX_SIGNAL_APPSERVICE_HS_TOKEN`, + + These environment variables can also be used to set other options by + replacing hierarchy levels by `.`, converting the name to uppercase + and prepending `MAUTRIX_SIGNAL_`. + For example, the first value above maps to + {option}`settings.appservice.as_token`. + + The environment variable values can be prefixed with `json::` to have + them be parsed as JSON. For example, `login_shared_secret_map` can be + set as follows: + `MAUTRIX_SIGNAL_BRIDGE_LOGIN_SHARED_SECRET_MAP=json::{"example.com":"secret"}`. + ''; + }; + + serviceDependencies = mkOption { + type = with types; listOf str; + default = optional config.services.matrix-synapse.enable "matrix-synapse.service"; + defaultText = literalExpression '' + optional config.services.matrix-synapse.enable "matrix-synapse.service" + ''; + description = lib.mdDoc '' + List of Systemd services to require and wait for when starting the application service. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + services.signald.enable = true; + + systemd.services.mautrix-signal = { + description = "Mautrix-Signal, a Matrix-Signal puppeting bridge."; + + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ] ++ cfg.serviceDependencies; + after = [ "network-online.target" ] ++ cfg.serviceDependencies; + path = [ pkgs.lottieconverter pkgs.ffmpeg-full ]; + + # TODO(2023-01-11): Still relevant in Go version? + # mautrix-signal tries to generate a dotfile in the home directory of + # the running user if using a postgresql database: + # + # File "python3.10/site-packages/asyncpg/connect_utils.py", line 257, in _dot_postgre> + # return (pathlib.Path.home() / '.postgresql' / filename).resolve() + # File "python3.10/pathlib.py", line 1000, in home + # return cls("~").expanduser() + # File "python3.10/pathlib.py", line 1440, in expanduser + # raise RuntimeError("Could not determine home directory.") + # RuntimeError: Could not determine home directory. + environment.HOME = dataDir; + + preStart = '' + # substitute the settings file by environment variables + # in this case read from EnvironmentFile + test -f '${settingsFile}' && rm -f '${settingsFile}' + old_umask=$(umask) + umask 0177 + ${pkgs.envsubst}/bin/envsubst \ + -o '${settingsFile}' \ + -i '${settingsFileUnsubstituted}' \ + umask $old_umask + + # generate the appservice's registration file if absent + if [ ! -f '${registrationFile}' ]; then + ${cfg.package}/bin/mautrix-signal \ + --generate-registration \ + --config='${settingsFile}' \ + --registration='${registrationFile}' + fi + chmod 640 ${registrationFile} + + umask 0177 + ${pkgs.yq}/bin/yq -s '.[0].appservice.as_token = .[1].as_token + | .[0].appservice.hs_token = .[1].hs_token + | .[0]' '${settingsFile}' '${registrationFile}' \ + > '${settingsFile}.tmp' + mv '${settingsFile}.tmp' '${settingsFile}' + umask $old_umask + ''; + + serviceConfig = { + Type = "simple"; + Restart = "always"; + + ProtectSystem = "strict"; + ProtectHome = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + + DynamicUser = true; + SupplementaryGroups = [ "signald" ]; + PrivateTmp = true; + WorkingDirectory = cfg.package; # necessary for the database migration scripts to be found + StateDirectory = baseNameOf dataDir; + UMask = "0027"; + EnvironmentFile = cfg.environmentFile; + + ExecStart = '' + ${cfg.package}/bin/mautrix-signal \ + --config='${settingsFile}' + ''; + + restartTriggers = [settingsFileUnsubstituted]; + }; + }; + }; + + # meta.maintainers = with maintainers; [ boppyt ]; +} diff --git a/modules/services/matrix-bridge/default.nix b/modules/services/matrix-bridge/default.nix new file mode 100644 index 0000000..4d53223 --- /dev/null +++ b/modules/services/matrix-bridge/default.nix @@ -0,0 +1,390 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.modules.services.matrix-bridge; +in +{ + imports = [ + ./_mautrix-signal-module.nix + ./_mautrix-discord-module.nix + ]; + + options.modules.services.matrix-bridge = { + enable = mkEnableOption "matrix-bridge"; + domain = mkOption { type = types.str; }; + realHost = mkOption { type = types.str; default = "matrix.${cfg.domain}"; }; + secrets.mautrix-envs = mkOption { type = types.path; description = "path to the mautrix-* environment file"; }; + }; + + config = mkIf cfg.enable { + sops.secrets.double-puppet-as-token = { }; + sops.secrets.double-puppet-hs-token = { }; + + sops.templates."double-puppet-registration.yaml".content = '' + id: doublepuppet + url: + as_token: ${config.sops.placeholder.double-puppet-as-token} + hs_token: ${config.sops.placeholder.double-puppet-hs-token} + sender_localpart: 55e126746dad19e50d9c4e646b6f5ac9ba21b346a24b840330cd8d8a1d65ce80 + rate_limited: false + namespaces: + users: + - regex: '@.*:exotic\.sh' + exclusive: false + ''; + + services.mautrix-telegram = { + enable = true; + + environmentFile = cfg.secrets.mautrix-envs; + serviceDependencies = [ "matrix-synapse.service" ]; + + settings = { + homeserver.address = "https://${cfg.realHost}"; + homeserver.domain = cfg.domain; + homeserver.verify_ssl = true; + appservice = { + address = "http://localhost:29317"; + hostname = "localhost"; + port = 29317; + database = "postgres:///mautrix-telegram?host=/run/postgresql"; + bot_avatar = "mxc://maunium.net/tJCRmUyJDsgRNgqhOgoiHWbX"; + id = "telegram"; + max_body_size = 1; + provisioning.enabled = false; + }; + bridge = { + alias_template = "tg_{groupname}"; + username_templace = "tg_{userid}"; + allow_matrix_login = true; + bot_messages_as_notices = true; + catch_up = true; + plaintext_highlights = true; + startup_sync = true; + animated_stickers = { + target = "webp"; + convert_from_webm = true; + }; + encryption = { + allow = true; + default = true; + require = true; + allow_key_sharing = true; + }; + # NOTE: python bridge - managed via env variable + # login_shared_secret_map = { + # "${cfg.domain}" = "as_token:$DOUBLE_PUPPET_AS_TOKEN"; + # }; + permissions = { + "@sef:exotic.sh" = "admin"; + "exotic.sh" = "full"; + }; + }; + }; + }; + + services.mautrix-signal = { + enable = true; + package = pkgs.mautrix-signal; + + environmentFile = cfg.secrets.mautrix-envs; + serviceDependencies = [ "matrix-synapse.service" ]; + + settings = { + homeserver.address = "https://${cfg.realHost}"; + homeserver.domain = cfg.domain; + homeserver.verify_ssl = true; + appservice = { + address = "http://localhost:29318"; + port = 29318; + database = "postgres:///mautrix-signal?host=/run/postgresql"; + bot_avatar = "mxc://maunium.net/wPJgTQbZOtpBFmDNkiNEMDUp"; + id = "signal"; + max_body_size = 1; + provisioning.enabled = false; + }; + + signal = { + avatar_dir = "/var/lib/signald/avatars"; + data_dir = "/var/lib/signald/data"; + }; + + bridge = { + alias_template = "sig_{groupname}"; + username_templace = "sig_{userid}"; + allow_matrix_login = true; + catch_up = true; + plaintext_highlights = true; + startup_sync = true; + animated_stickers = { + target = "webp"; + convert_from_webm = true; + }; + encryption = { + allow = true; + default = true; + require = true; + allow_key_sharing = true; + }; + login_shared_secret_map = { + "${cfg.domain}" = "as_token:$DOUBLE_PUPPET_AS_TOKEN"; + }; + permissions = { + "@sef:exotic.sh" = "admin"; + "exotic.sh" = "full"; + }; + }; + }; + }; + + services.mautrix-whatsapp = { + enable = true; + environmentFile = cfg.secrets.mautrix-envs; + serviceDependencies = [ "matrix-synapse.service" ]; + + settings = { + homeserver.address = "https://${cfg.realHost}"; + homeserver.domain = cfg.domain; + homeserver.verify_ssl = true; + appservice = { + address = "http://localhost:29319"; + hostname = "localhost"; + port = 29319; + database = { + type = "postgres"; + uri = "postgres://mautrix-whatsapp:@/mautrix-whatsapp?host=/run/postgresql"; + }; + bot_avatar = "mxc://maunium.net/NeXNQarUbrlYBiPCpprYsRqr"; + id = "whatsapp"; + max_body_size = 1; + provisioning.enabled = false; + }; + + bridge = { + alias_template = "wa_{groupname}"; + username_templace = "wa_{userid}"; + personal_filtering_spaces = true; + delivery_receipts = true; + identity_change_notices = true; + history_sync = { + backfill = false; # MSC2716 + request_full_sync = true; + }; + send_presence_on_typing = true; + double_puppet_server_map = { }; + login_shared_secret_map = { + "${cfg.domain}" = "as_token:$DOUBLE_PUPPET_AS_TOKEN"; + }; + private_chat_portal_meta = true; + mute_bridging = true; + pinned_tag = "m.favourite"; + archive_tag = "m.lowpriority"; + allow_user_invite = true; + disappearing_messages_in_groups = true; + url_previews = true; + encryption = { + allow = true; + default = true; + require = true; + allow_key_sharing = true; + }; + sync_manual_marked_unread = true; + force_active_delivery_receipts = true; + parallel_member_sync = true; + extev_polls = true; + send_whatsapp_edits = true; + permissions = { + "@sef:exotic.sh" = "admin"; + "exotic.sh" = "full"; + }; + }; + }; + }; + + services.mautrix-discord = { + enable = true; + environmentFile = cfg.secrets.mautrix-envs; + serviceDependencies = [ "matrix-synapse.service" ]; + + settings = { + homeserver.address = "https://${cfg.realHost}"; + homeserver.domain = cfg.domain; + homeserver.verify_ssl = true; + appservice = { + address = "http://localhost:29320"; + port = 29320; + database = { + type = "postgres"; + uri = "postgres://mautrix-discord:@/mautrix-discord?host=/run/postgresql"; + }; + bot_avatar = "mxc://maunium.net/nIdEykemnwdisvHbpxflpDlC"; + id = "discord"; + max_body_size = 1; + provisioning.enabled = false; + }; + + bridge = { + username_template = "dsc_{{.}}"; + delivery_receipts = true; + encryption = { + allow = true; + default = true; + require = true; + allow_key_sharing = true; + }; + login_shared_secret_map = { + "${cfg.domain}" = "as_token:$DOUBLE_PUPPET_AS_TOKEN"; + }; + permissions = { + "@sef:exotic.sh" = "admin"; + "exotic.sh" = "full"; + }; + }; + }; + }; + + services.matrix-appservice-irc = { + enable = true; + registrationUrl = "http://localhost:29321"; + port = 29321; + + settings = { + homeserver.url = "https://${cfg.realHost}"; + homeserver.domain = cfg.domain; + homeserver.dropMatrixMessagesAfterSecs = 600; # 10 minutes + + database.engine = "postgres"; + database.connectionString = "postgres://matrix-appservice-irc:@/matrix-appservice-irc?host=/run/postgresql"; + + ircService.servers = let + # nix-community/nur-combined/repos/colinsane/hosts/by-name/servo/services/matrix/irc.nix@b2e96d5 + ircServer = { name, additionalAddresses ? [], sasl ? true, port ? 6697}: + let lowerName = lib.toLower name; + in { + inherit name additionalAddresses sasl port; + ssl = true; + # Disable bridging of Matrix bots + botConfig.enabled = false; + dynamicChannels = { + enabled = true; + aliasTemplate = "#irc_${lowerName}_$CHANNEL"; + published = false; + federate = false; + }; + ircClients = { + nickTemplate = "$DISPLAY[m]"; + allowNickChanges = true; + realNameFormat = "reverse-mxid"; + lineLimit = 20; + # Safeguard: don't flood servers + maxClients = 2; + idleTimeout = 0; + concurrentReconnectLimit = 2; + reconnectIntervalMs = 60000; + kickOn = { + # only kick Matrix user from room when user quits + channelJoinFailure = false; + ircConnectionFailure = false; + userQuit = true; + }; + }; + matrixClients.userTemplate = "@irc_${lowerName}_$NICK"; + + "@sef:exotic.sh" = "admin"; + + memberShipLists = { + enabled = true; + # NOTE: when serving lots of Matrix users, these configs should + # be changed to reduce strain on IRC servers + global = { + ircToMatrix = { + initial = true; + incremental = true; + requireMatrixJoined = false; + }; + matrixToIrc = { + initial = true; + incremental = true; + }; + # always bridge users, even if idle + ignoreIdleUsersOnStartup.enabled = false; + }; + bridgeInfoState = { + enabled = true; + initial = true; + }; + }; + }; + in { + "irc.libera.chat" = ircServer { + name = "libera"; + # sasl = false; + }; + "irc.oftc.net" = ircServer { + name = "oftc"; + # sasl = false; + }; + }; + }; + }; + + # HACK: https://github.com/NixOS/nixpkgs/issues/273929 + systemd.services.matrix-appservice-irc.serviceConfig.SystemCallFilter = lib.mkForce '' + @system-service @pkey ~@privileged @resources @chown + ''; + + + modules.persistence.directories = [ + "/var/lib/private/mautrix-telegram" + "/var/lib/private/mautrix-signal" + "/var/lib/private/mautrix-whatsapp" + "/var/lib/private/mautrix-discord" + "/var/lib/matrix-appservice-irc" + "/var/lib/signald" + ]; + + modules.services.postgresql.enable = true; + services.postgresql.ensureDatabases = [ "mautrix-telegram" "mautrix-signal" "mautrix-whatsapp" "mautrix-discord" "matrix-appservice-irc" ]; + services.postgresql.ensureUsers = [ + { + name = "mautrix-telegram"; + ensureDBOwnership = true; + } + { + name = "mautrix-signal"; + ensureDBOwnership = true; + } + { + name = "mautrix-whatsapp"; + ensureDBOwnership = true; + } + { + name = "mautrix-discord"; + ensureDBOwnership = true; + } + { + name = "matrix-appservice-irc"; + ensureDBOwnership = true; + } + ]; + + systemd.services.matrix-synapse.serviceConfig.LoadCredential = [ + "mautrix-telegram:/var/lib/mautrix-telegram/telegram-registration.yaml" + "mautrix-signal:/var/lib/mautrix-signal/signal-registration.yaml" + "mautrix-whatsapp:/var/lib/mautrix-whatsapp/whatsapp-registration.yaml" + "mautrix-discord:/var/lib/mautrix-discord/discord-registration.yaml" + "double-puppet:${config.sops.templates."double-puppet-registration.yaml".path}" + "appservice-irc:/var/lib/matrix-appservice-irc/registration.yml" + ]; + + services.matrix-synapse.settings.app_service_config_files = [ + "/run/credentials/matrix-synapse.service/mautrix-telegram" + "/run/credentials/matrix-synapse.service/mautrix-signal" + "/run/credentials/matrix-synapse.service/mautrix-whatsapp" + "/run/credentials/matrix-synapse.service/mautrix-discord" + "/run/credentials/matrix-synapse.service/double-puppet" + "/run/credentials/matrix-synapse.service/appservice-irc" + ]; + }; +} |