zaphyra's git: nixfiles

zaphyra and void's nixfiles

commit 92f104b834c4c3dc4735b9e6bb7ee0294b0620e6
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
config/nixos/modules/services/mautrixBridge.nix
|
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" ];
+      };
+    }
+  );
+
+}