{ 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"; }; environmentFile = lib.mkOption { type = with types; nullOr str; default = null; }; 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 != { }) { systemd.services = ( cfg.paths |> lib.attrsToList |> lib.map ( element: ( if element.value.enable then ( element.value.targets |> lib.map ( target: lib.nameValuePair "restic-backups-${element.name}-${target}" { serviceConfig.EnvironmentFile = [ cfg.targets."${target}".environmentFile ] ++ (lib.optionals (element.value.environmentFile != null) [ element.value.environmentFile ]); } ) ) else [ ] ) ) |> lib.flatten |> lib.listToAttrs ); 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}"; 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 ); }; }