zaphyra's git: nixfiles

zaphyra and void's nixfiles

commit 13d213e83a53b3823af22a0b0470c68cdceee1ef
parent 59e93f92d8c98caf770084a84f8b8fc836b5493c
Author: Katja (zaphyra) <git@ctu.cx>
Date: Fri, 23 May 2025 11:28:51 +0200

config/nixos/modules/services: add `resticBackup`
1 file changed, 164 insertions(+), 0 deletions(-)
A
config/nixos/modules/services/resticBackup.nix
|
164
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/config/nixos/modules/services/resticBackup.nix b/config/nixos/modules/services/resticBackup.nix
@@ -0,0 +1,164 @@
+{
+  povSelf,
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  inherit (lib) types;
+  cfg = lib.getAttrFromPath povSelf config;
+
+in
+{
+
+  options = {
+    targets = {
+      default = { };
+      type = types.attrsOf (
+        types.submodule {
+          options = {
+            repository = lib.mkOption {
+              type = with types; nullOr str;
+              default = null;
+            };
+            environmentFile = lib.mkOption {
+              type = with types; nullOr path;
+              default = null;
+            };
+          };
+        }
+      );
+    };
+    paths = {
+      default = { };
+      type = types.attrsOf (
+        types.submodule {
+          options = {
+            enable = lib.mkOption {
+              type = types.bool;
+              default = false;
+            };
+            user = lib.mkOption {
+              type = types.str;
+              default = "root";
+            };
+            passwordFile = lib.mkOption {
+              type = types.str;
+            };
+            targets = lib.mkOption {
+              type = with types; listOf str;
+              default = lib.attrNames cfg.targets;
+            };
+            timerConfig = lib.mkOption {
+              type = types.attrs;
+              default = {
+                OnCalendar = "daily";
+                RandomizedDelaySec = 1200;
+              };
+            };
+            paths = lib.mkOption {
+              type = with types; listOf str;
+              default = [ ];
+            };
+            runBeforeBackup = lib.mkOption {
+              type = types.str;
+              default = "";
+            };
+            postgresDatabases = lib.mkOption {
+              type = with types; listOf str;
+              default = [ ];
+            };
+            sqliteDatabases = lib.mkOption {
+              type = with types; listOf str;
+              default = [ ];
+            };
+            influxBuckets = lib.mkOption {
+              type = with types; listOf str;
+              default = [ ];
+            };
+          };
+        }
+      );
+    };
+  };
+
+  config = lib.mkIf (cfg.paths != { }) {
+    services.restic.backups = (
+      cfg.paths
+      |> lib.attrsToList
+      |> lib.map (
+        element:
+        (
+          if element.value.enable then
+            (
+              element.value.targets
+              |> lib.map (
+                target:
+                lib.nameValuePair "${element.name}-${target}" {
+                  initialize = true;
+                  user = element.value.user;
+                  passwordFile = element.value.passwordFile;
+                  timerConfig = element.value.timerConfig;
+                  repository = cfg.targets."${target}".repository + "/${config.networking.hostName}-${element.name}";
+                  environmentFile = cfg.targets."${target}".environmentFile;
+                  paths = lib.mkMerge [
+                    element.value.paths
+                    (lib.mkIf (element.value.postgresDatabases != [ ]) (
+                      lib.map (element: "/tmp/postgresDatabases/${element}.sql.zst") element.value.postgresDatabases
+                    ))
+                    (lib.mkIf (element.value.sqliteDatabases != [ ]) (
+                      lib.map (
+                        element: "/tmp/sqliteDatabases/${builtins.baseNameOf element}.sqlite"
+                      ) element.value.sqliteDatabases
+                    ))
+                    (lib.mkIf (element.value.influxBuckets != [ ]) (
+                      lib.map (element: "/tmp/influxBuckets/${element}") element.value.influxBuckets
+                    ))
+                  ];
+                  backupPrepareCommand = (
+                    element.value.runBeforeBackup
+                    +
+                      #dump postgresql databases
+                      (lib.optionalString (element.value.postgresDatabases != [ ]) (
+                        lib.concatMapStringsSep "\n" (db: ''
+                          echo "Dumping Postgres-database: ${db}"
+                          mkdir -p /tmp/postgresDatabases
+                          pg_dump ${db} | zstd --rsyncable > /tmp/postgresDatabases/${db}.sql.zst
+                          [ $(du -b /tmp/postgresDatabases/${db}.sql.zst | cut -f1) -gt "50" ] || exit 1
+                        '') element.value.postgresDatabases
+                      ))
+                    +
+                      #dump sqlite databases
+                      (lib.optionalString (element.value.sqliteDatabases != [ ]) (
+                        lib.concatMapStringsSep "\n" (db: ''
+                          echo "Dumping sqlite-database: ${db}"
+                          mkdir -p /tmp/sqliteDatabases
+                          ${pkgs.sqlite}/bin/sqlite3 ${db} ".backup '/tmp/sqliteDatabases/${builtins.baseNameOf db}.sqlite'"
+                          [ $(du -b /tmp/sqliteDatabases/${builtins.baseNameOf db}.sqlite-backup | cut -f1) -gt "50" ] || exit 1
+                        '') element.value.sqliteDatabases
+                      ))
+                    +
+                      #dump influx buckets
+                      (lib.optionalString (element.value.influxBuckets != [ ]) (
+                        lib.concatMapStringsSep "\n" (db: ''
+                          echo "Dumping influx-bucket: ${db}"
+                          mkdir -p /tmp/influxBuckets
+                          ${pkgs.influxdb2}/bin/influx backup --compression=none --bucket=${db} /tmp/influxBuckets/${db}
+                          [ $(du -b /tmp/influxBuckets/${db} | cut -f1) -gt "50" ] || exit 1
+                        '') element.value.influxBuckets
+                      ))
+                  );
+                }
+              )
+            )
+          else
+            [ ]
+        )
+      )
+      |> lib.flatten
+      |> lib.listToAttrs
+    );
+  };
+
+}