commit a3d642d87fbd4d938e9628dda320478adf842090
parent 364008e649fab88b7dc68b6c0e14c71104e5c704
Author: Katja (ctucx) <git@ctu.cx>
Date: Tue, 25 Mar 2025 13:12:05 +0100
parent 364008e649fab88b7dc68b6c0e14c71104e5c704
Author: Katja (ctucx) <git@ctu.cx>
Date: Tue, 25 Mar 2025 13:12:05 +0100
modules/nixos: refactor mautrix-bridges to use single module-file
8 files changed, 129 insertions(+), 389 deletions(-)
A
|
121
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D
|
122
-------------------------------------------------------------------------------
D
|
122
-------------------------------------------------------------------------------
D
|
122
-------------------------------------------------------------------------------
diff --git a/configurations/nixos/services/matrixBridges/mautrix-signal.nix b/configurations/nixos/services/matrixBridges/mautrix-signal.nix @@ -4,12 +4,8 @@ age.secrets.mautrixSignalEnv.file = secrets."${config.networking.hostName}".mautrixSignalEnv; - nixpkgs.overlays = [ (final: prev: { - mautrix-signal = prev.mautrix-signal.override { withGoolm = true; }; - }) ]; - - services.mautrix-signal = { - enable = true; + services.mautrix-bridge.signal = { + package = pkgs.mautrix-signal.override { withGoolm = true; }; environmentFile = config.age.secrets.mautrixSignalEnv.path; serviceDependencies = [ "conduwuit.service" ]; settings = rec {
diff --git a/configurations/nixos/services/matrixBridges/mautrix-telegram.nix b/configurations/nixos/services/matrixBridges/mautrix-telegram.nix @@ -4,12 +4,8 @@ age.secrets.mautrixTelegramEnv.file = secrets."${config.networking.hostName}".mautrixTelegramEnv; - nixpkgs.overlays = [ (final: prev: { - mautrix-telegramgo = prev.mautrix-telegram.override { withGoolm = true; }; - }) ]; - - services.mautrix-telegram = { - enable = true; + services.mautrix-bridge.telegram = { + package = pkgs.mautrix-telegramgo.override { withGoolm = true; }; environmentFile = config.age.secrets.mautrixTelegramEnv.path; serviceDependencies = [ "conduwuit.service" ]; settings = rec {
diff --git a/configurations/nixos/services/matrixBridges/mautrix-whatsapp.nix b/configurations/nixos/services/matrixBridges/mautrix-whatsapp.nix @@ -4,12 +4,8 @@ age.secrets.mautrixWhatsAppEnv.file = secrets."${config.networking.hostName}".mautrixWhatsAppEnv; - nixpkgs.overlays = [ (final: prev: { - mautrix-whatsapp = prev.mautrix-whatsapp.override { withGoolm = true; }; - }) ]; - - services.mautrix-whatsapp = { - enable = true; + services.mautrix-bridge.whatsapp = { + package = pkgs.mautrix-whatsapp.override { withGoolm = true; }; serviceDependencies = [ "conduwuit.service" ]; environmentFile = config.age.secrets.mautrixWhatsAppEnv.path; settings = rec {
diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix @@ -1,5 +1,4 @@ - -{ lib, ... }: +{ ... }: { @@ -22,10 +21,8 @@ ./gotosocial.nix ./gnome.nix ./conduwuit.nix - ./mautrix-whatsapp.nix - ./mautrix-signal.nix - ./mautrix-telegram.nix ./gomuks-web.nix + ./mautrix-bridge.nix ]; }
diff --git a/modules/nixos/mautrix-bridge.nix b/modules/nixos/mautrix-bridge.nix @@ -0,0 +1,121 @@ +{ config, lib, pkgs, ... }: + +let + forEachInstance = + f: + lib.flip lib.mapAttrs' config.services.mautrix-bridge ( + name: cfg: lib.nameValuePair "mautrix-bridge-${name}" (f name cfg) + ); + +in { + + options.services.mautrix-bridge = lib.mkOption { + default = {}; + type = lib.types.attrsOf ( + lib.types.submodule ({ + options = { + package = lib.mkOption { type = lib.types.package; }; + settings = lib.mkOption { type = (pkgs.formats.json {}).type; default = {}; }; + environmentFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; }; + serviceDependencies = lib.mkOption { type = lib.types.listOf lib.types.str; default = []; }; + }; + }) + ); + }; + + config.systemd.services = forEachInstance (name: cfg: let + dataDir = "/var/lib/mautrix-${name}"; + registrationFile = "${dataDir}/registration.yaml"; + settingsFile = "${dataDir}/config.yaml"; + settingsFileUnsubstituted = (pkgs.formats.json {}).generate "mautrix-${name}-config-unsubstituted.json" cfg.settings; + in { + description = "mautrix-bridge-${name}, a matrix puppeting bridge."; + restartTriggers = [ settingsFileUnsubstituted ]; + + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ] ++ cfg.serviceDependencies; + after = [ "network-online.target" ] ++ cfg.serviceDependencies; + + path = [ pkgs.ffmpeg-headless ]; + + 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 + ${lib.getExe cfg.package} \ + --generate-registration \ + --config='${settingsFile}' \ + --registration='${registrationFile}' + fi + chmod 640 ${registrationFile} + + umask 0177 + ${pkgs.yq}/bin/yq -s ' + .[0].appservice.as_token = (.[0].appservice.as_token // .[1].as_token) + | .[0].appservice.hs_token = (.[0].appservice.hs_token // .[1].hs_token) + ${lib.optionalString (name == "telegram") " + | .[0].network.api_id = (.[0].network.api_id | tonumber) + "} + | .[0]' \ + '${settingsFile}' '${registrationFile}' > '${settingsFile}.tmp' + mv '${settingsFile}.tmp' '${settingsFile}' + umask $old_umask + ''; + + serviceConfig = { + Type = "exec"; + + DynamicUser = true; + User = "mautrix-bridge-${name}"; + Group = "mautrix-bridge-${name}"; + + EnvironmentFile = cfg.environmentFile; + StateDirectory = baseNameOf dataDir; + WorkingDirectory = dataDir; + UMask = 27; + + ExecStart = '' + ${lib.getExe cfg.package} \ + --no-update \ + --config='${settingsFile}' + ''; + + Restart = "on-failure"; + RestartSec = "30s"; + + LockPersonality = true; + NoNewPrivileges = true; + MemoryDenyWriteExecute = lib.mkIf (name != "signal") true; + + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + + ProtectSystem = "strict"; + ProtectClock = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectControlGroups = true; + + RestrictRealtime = true; + RestrictSUIDSGID = true; + + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = [ "@system-service" ]; + }; + }); + +}
diff --git a/modules/nixos/mautrix-signal.nix b/modules/nixos/mautrix-signal.nix @@ -1,122 +0,0 @@ -{ lib, config, pkgs, ... }: - -let - cfg = config.services.mautrix-signal; - dataDir = "/var/lib/mautrix-signal"; - registrationFile = "${dataDir}/signal-registration.yaml"; - settingsFile = "${dataDir}/config.yaml"; - settingsFileUnsubstituted = settingsFormat.generate "mautrix-signal-config-unsubstituted.json" cfg.settings; - settingsFormat = pkgs.formats.json { }; - -in { - - options.services.mautrix-signal = { - enable = lib.mkEnableOption "mautrix-signal, a Matrix-Signal puppeting bridge"; - - settings = lib.mkOption { - type = settingsFormat.type; - default = {}; - }; - - environmentFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - }; - - serviceDependencies = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = []; - }; - }; - - config = lib.mkIf cfg.enable { - users.groups.mautrix-signal = { }; - users.users.mautrix-signal = { - isSystemUser = true; - group = "mautrix-signal"; - home = dataDir; - description = "Mautrix-Signal bridge user"; - }; - - systemd.services.mautrix-signal = { - description = "mautrix-signal, a Matrix-Signal puppeting bridge."; - restartTriggers = [ settingsFileUnsubstituted ]; - - wantedBy = [ "multi-user.target" ]; - wants = [ "network-online.target" ] ++ cfg.serviceDependencies; - after = [ "network-online.target" ] ++ cfg.serviceDependencies; - # ffmpeg is required for conversion of voice messages - path = [ pkgs.ffmpeg-headless ]; - - 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-signal}/bin/mautrix-signal \ - --generate-registration \ - --config='${settingsFile}' \ - --registration='${registrationFile}' - fi - chmod 640 ${registrationFile} - - umask 0177 - # 1. Overwrite registration tokens in config - # 2. If environment variable MAUTRIX_SIGNAL_BRIDGE_LOGIN_SHARED_SECRET - # is set, set it as the login shared secret value for the configured - # homeserver domain. - ${pkgs.yq}/bin/yq -s '.[0].appservice.as_token = .[1].as_token - | .[0].appservice.hs_token = .[1].hs_token - | .[0] - | if env.MAUTRIX_SIGNAL_BRIDGE_LOGIN_SHARED_SECRET then .double_puppet.secrets.[.homeserver.domain] = env.MAUTRIX_SIGNAL_BRIDGE_LOGIN_SHARED_SECRET else . end' \ - '${settingsFile}' '${registrationFile}' > '${settingsFile}.tmp' - mv '${settingsFile}.tmp' '${settingsFile}' - umask $old_umask - ''; - - serviceConfig = { - User = "mautrix-signal"; - Group = "mautrix-signal"; - EnvironmentFile = cfg.environmentFile; - StateDirectory = baseNameOf dataDir; - WorkingDirectory = dataDir; - ExecStart = '' - ${pkgs.mautrix-signal}/bin/mautrix-signal \ - --config='${settingsFile}' \ - --registration='${registrationFile}' - ''; - LockPersonality = true; - NoNewPrivileges = true; - PrivateDevices = true; - PrivateTmp = true; - PrivateUsers = true; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - ProtectSystem = "strict"; - Restart = "on-failure"; - RestartSec = "30s"; - RestrictRealtime = true; - RestrictSUIDSGID = true; - SystemCallArchitectures = "native"; - SystemCallErrorNumber = "EPERM"; - SystemCallFilter = [ "@system-service" ]; - Type = "simple"; - UMask = 27; - }; - }; - }; - -}
diff --git a/modules/nixos/mautrix-telegram.nix b/modules/nixos/mautrix-telegram.nix @@ -1,122 +0,0 @@ -{ lib, config, pkgs, ... }: - -let - cfg = config.services.mautrix-telegram; - dataDir = "/var/lib/mautrix-telegram"; - registrationFile = "${dataDir}/telegram-registration.yaml"; - settingsFile = "${dataDir}/config.yaml"; - settingsFileUnsubstituted = settingsFormat.generate "mautrix-telegram-config-unsubstituted.json" cfg.settings; - settingsFormat = pkgs.formats.json { }; - -in { - - options.services.mautrix-telegram = { - enable = lib.mkEnableOption "mautrix-telegram, a Matrix-Telegram puppeting bridge"; - - settings = lib.mkOption { - type = settingsFormat.type; - default = {}; - }; - - environmentFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - }; - - serviceDependencies = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = []; - }; - }; - - config = lib.mkIf cfg.enable { - users.groups.mautrix-telegram = { }; - users.users.mautrix-telegram = { - isSystemUser = true; - group = "mautrix-telegram"; - home = dataDir; - description = "Mautrix-Telegram bridge user"; - }; - - systemd.services.mautrix-telegram = { - description = "mautrix-telegram, a Matrix-Telegram puppeting bridge."; - restartTriggers = [ settingsFileUnsubstituted ]; - - wantedBy = [ "multi-user.target" ]; - wants = [ "network-online.target" ] ++ cfg.serviceDependencies; - after = [ "network-online.target" ] ++ cfg.serviceDependencies; - path = [ pkgs.ffmpeg-headless ]; - - 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 - ${lib.getExe pkgs.mautrix-telegramgo} \ - --generate-registration \ - --config='${settingsFile}' \ - --registration='${registrationFile}' - fi - chmod 640 ${registrationFile} - - umask 0177 - # 1. Overwrite registration tokens in config - # 2. If environment variable MAUTRIX_SIGNAL_BRIDGE_LOGIN_SHARED_SECRET - # is set, set it as the login shared secret value for the configured - # homeserver domain. - ${pkgs.yq}/bin/yq -s '.[0].network.api_id = (.[0].network.api_id | tonumber) - | .[0].appservice.as_token = .[1].as_token - | .[0].appservice.hs_token = .[1].hs_token - | .[0] - | if env.MAUTRIX_TELEGRAM_BRIDGE_LOGIN_SHARED_SECRET then .double_puppet.secrets.[.homeserver.domain] = env.MAUTRIX_TELEGRAM_BRIDGE_LOGIN_SHARED_SECRET else . end' \ - '${settingsFile}' '${registrationFile}' > '${settingsFile}.tmp' - mv '${settingsFile}.tmp' '${settingsFile}' - umask $old_umask - ''; - - serviceConfig = { - User = "mautrix-telegram"; - Group = "mautrix-telegram"; - EnvironmentFile = cfg.environmentFile; - StateDirectory = baseNameOf dataDir; - WorkingDirectory = dataDir; - ExecStart = '' - ${lib.getExe pkgs.mautrix-telegramgo} \ - --config='${settingsFile}' \ - --registration='${registrationFile}' - ''; - LockPersonality = true; - NoNewPrivileges = true; - PrivateDevices = true; - PrivateTmp = true; - PrivateUsers = true; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - ProtectSystem = "strict"; - Restart = "on-failure"; - RestartSec = "30s"; - RestrictRealtime = true; - RestrictSUIDSGID = true; - SystemCallArchitectures = "native"; - SystemCallErrorNumber = "EPERM"; - SystemCallFilter = [ "@system-service" ]; - Type = "simple"; - UMask = 27; - }; - }; - }; - -}
diff --git a/modules/nixos/mautrix-whatsapp.nix b/modules/nixos/mautrix-whatsapp.nix @@ -1,122 +0,0 @@ -{ lib, config, pkgs, ... }: - -let - cfg = config.services.mautrix-whatsapp; - dataDir = "/var/lib/mautrix-whatsapp"; - registrationFile = "${dataDir}/whatsapp-registration.yaml"; - settingsFile = "${dataDir}/config.yaml"; - settingsFileUnsubstituted = settingsFormat.generate "mautrix-whatsapp-config-unsubstituted.json" cfg.settings; - settingsFormat = pkgs.formats.json {}; - -in { - - options.services.mautrix-whatsapp = { - enable = lib.mkEnableOption "mautrix-whatsapp, a puppeting/relaybot bridge between Matrix and WhatsApp"; - - settings = lib.mkOption { - type = settingsFormat.type; - default = {}; - }; - - environmentFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - }; - - serviceDependencies = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = []; - }; - }; - - config = lib.mkIf cfg.enable { - users.groups.mautrix-whatsapp = {}; - users.users.mautrix-whatsapp = { - isSystemUser = true; - group = "mautrix-whatsapp"; - home = dataDir; - description = "Mautrix-WhatsApp bridge user"; - }; - - systemd.services.mautrix-whatsapp = { - description = "Mautrix-WhatsApp Service - A WhatsApp bridge for Matrix"; - restartTriggers = [ settingsFileUnsubstituted ]; - - 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-whatsapp}/bin/mautrix-whatsapp \ - --generate-registration \ - --config='${settingsFile}' \ - --registration='${registrationFile}' - fi - chmod 640 ${registrationFile} - - umask 0177 - # 1. Overwrite registration tokens in config - # 2. If environment variable MAUTRIX_WHATSAPP_BRIDGE_LOGIN_SHARED_SECRET - # is set, set it as the login shared secret value for the configured - # homeserver domain. - ${pkgs.yq}/bin/yq -s '.[0].appservice.as_token = .[1].as_token - | .[0].appservice.hs_token = .[1].hs_token - | .[0] - | if env.MAUTRIX_WHATSAPP_BRIDGE_LOGIN_SHARED_SECRET then .bridge.login_shared_secret_map.[.homeserver.domain] = env.MAUTRIX_WHATSAPP_BRIDGE_LOGIN_SHARED_SECRET else . end' \ - '${settingsFile}' '${registrationFile}' > '${settingsFile}.tmp' - mv '${settingsFile}.tmp' '${settingsFile}' - umask $old_umask - ''; - - serviceConfig = { - User = "mautrix-whatsapp"; - Group = "mautrix-whatsapp"; - EnvironmentFile = cfg.environmentFile; - StateDirectory = baseNameOf dataDir; - WorkingDirectory = dataDir; - ExecStart = '' - ${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp \ - --config='${settingsFile}' \ - --registration='${registrationFile}' - ''; - LockPersonality = true; - MemoryDenyWriteExecute = true; - NoNewPrivileges = true; - PrivateDevices = true; - PrivateTmp = true; - PrivateUsers = true; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - ProtectSystem = "strict"; - Restart = "on-failure"; - RestartSec = "30s"; - RestrictRealtime = true; - RestrictSUIDSGID = true; - SystemCallArchitectures = "native"; - SystemCallErrorNumber = "EPERM"; - SystemCallFilter = ["@system-service"]; - Type = "simple"; - UMask = 0027; - }; - }; - }; - -}