commit 92f104b834c4c3dc4735b9e6bb7ee0294b0620e6
parent fffc089f7d74a3618564d8a4e3bea88cbae2e77b
Author: Katja (zaphyra) <git@ctu.cx>
Date: Mon, 26 May 2025 10:19:15 +0200
parent fffc089f7d74a3618564d8a4e3bea88cbae2e77b
Author: Katja (zaphyra) <git@ctu.cx>
Date: Mon, 26 May 2025 10:19:15 +0200
config/nixos/modules/services: add `mautrixBridge`
1 file changed, 152 insertions(+), 0 deletions(-)
A
|
152
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/config/nixos/modules/services/mautrixBridge.nix b/config/nixos/modules/services/mautrixBridge.nix @@ -0,0 +1,152 @@ +{ + povSelf, + config, + lib, + pkgs, + ... +}: +let + inherit (lib) types; + forEachInstance = + f: + lib.flip lib.mapAttrs' (lib.getAttrFromPath povSelf config) ( + name: cfg: lib.nameValuePair "mautrixBridge-${name}" (f name cfg) + ); + +in +{ + + option = { + default = { }; + type = types.attrsOf ( + types.submodule ({ + options = { + enable = lib.mkOption { + type = types.bool; + default = false; + }; + package = lib.mkOption { + type = types.package; + }; + settings = lib.mkOption { + type = (pkgs.formats.json { }).type; + default = { }; + }; + environmentFile = lib.mkOption { + type = with types; nullOr path; + default = null; + }; + serviceDependencies = lib.mkOption { + type = with types; listOf 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 + { + enable = cfg.enable; + description = "mautrixBridge-${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 = "mautrixBridge-${name}"; + Group = "mautrixBridge-${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" ]; + }; + } + ); + +}