commit cbe37317aaa73bda49bd7194b226beda1fd06a8b
parent 7bf2e9c19c8633a06f0d035a4867feebc99af1fb
Author: Katja Ramona Sophie Kwast (zaphyra) <git@zaphyra.eu>
Date: Tue, 19 Aug 2025 13:28:12 +0200
parent 7bf2e9c19c8633a06f0d035a4867feebc99af1fb
Author: Katja Ramona Sophie Kwast (zaphyra) <git@zaphyra.eu>
Date: Tue, 19 Aug 2025 13:28:12 +0200
nixosModules: add `mautrixBridge`
1 file changed, 155 insertions(+), 0 deletions(-)
A
|
155
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/nixosModules/services/mautrixBridge/default.nix b/nixosModules/services/mautrixBridge/default.nix @@ -0,0 +1,155 @@ +{ ... }: +{ + config, + lib, + pkgs, + ... +}: + +let + inherit (lib) types; + cfg = config.tgc.services.mautrixBridge; + forEachInstance = + f: lib.flip lib.mapAttrs' cfg (name: cfg: lib.nameValuePair "mautrixBridge-${name}" (f name cfg)); + +in +{ + + # todo: add some documentation + options.tgc.services.mautrixBridge = lib.mkOption { + 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 = { + modules.filesystem.impermanence.system.dirs = ( + (lib.attrNames cfg) |> lib.map (element: "/var/lib/private/mautrix-${element}") + ); + + 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 + #todo: switch to `yq-go` + ${lib.getExe pkgs.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" ]; + }; + } + ); + }; + +}