diff options
| author | Max Audron <audron@cocaine.farm> | 2026-01-07 15:28:01 +0100 |
|---|---|---|
| committer | Max Audron <audron@cocaine.farm> | 2026-01-07 15:28:01 +0100 |
| commit | 84739ac2345265e518a50bc2e9a239eb442e6e22 (patch) | |
| tree | e289c856e5465f0c713e97a0ba86e1f734c3484e /modules/backup/policy.nix | |
| parent | add kopia module (diff) | |
setup backups for mail
Diffstat (limited to 'modules/backup/policy.nix')
| -rw-r--r-- | modules/backup/policy.nix | 410 |
1 files changed, 214 insertions, 196 deletions
diff --git a/modules/backup/policy.nix b/modules/backup/policy.nix index 5486cac..ab7fb7d 100644 --- a/modules/backup/policy.nix +++ b/modules/backup/policy.nix @@ -28,221 +28,232 @@ let "zstd-fastest" ]; + policyListType = lib.mkOption { + type = lib.types.listOf policySubmodule; + default = []; + }; + policyType = lib.mkOption { - type = lib.types.nullOr ( - lib.types.submodule { - options = { - retention = { - keepLatest = lib.mkOption { - type = lib.types.int; - default = 5; - description = "Number of latest snapshots to keep."; - }; - keepHourly = lib.mkOption { - type = lib.types.int; - default = 48; - description = "Number of hourly snapshots to keep."; - }; - keepDaily = lib.mkOption { - type = lib.types.int; - default = 7; - description = "Number of daily snapshots to keep."; - }; - keepWeekly = lib.mkOption { - type = lib.types.int; - default = 4; - description = "Number of weekly snapshots to keep."; - }; - keepMonthly = lib.mkOption { - type = lib.types.int; - default = 3; - description = "Number of monthly snapshots to keep."; - }; - keepAnnual = lib.mkOption { - type = lib.types.int; - default = 0; - description = "Number of yearly snapshots to keep."; - }; - }; + type = lib.types.nullOr policySubmodule; + default = null; + }; - files = { - ignoreDotFiles = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ - ".gitignore" - ".kopiaignore" - ]; - description = "List of files to source ignore lists from."; - }; - noParentDotFiles = lib.mkOption { - type = lib.types.nullOr lib.types.bool; - default = false; - description = "Do not use parent ignore dot files."; - }; - ignoreCacheDirs = lib.mkOption { - type = lib.types.nullOr lib.types.bool; - default = false; - description = "Ignore cache directories."; - }; - maxFileSize = lib.mkOption { - type = lib.types.nullOr lib.types.int; - default = null; - description = "Maximum file size to include in backup."; - }; - oneFileSystem = lib.mkOption { - type = lib.types.nullOr lib.types.bool; - default = null; - description = "Stay in parent filesystem when finding files."; - }; - }; + policySubmodule = lib.types.submodule { + options = { + path = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = "Path for which the policy applies"; + }; - errorHandling = { - ignoreFileErrors = lib.mkOption { - type = lib.types.nullOr lib.types.bool; - default = null; - description = "Ignore errors reading ignore files."; - }; - ignoreDirectoryErrors = lib.mkOption { - type = lib.types.nullOr lib.types.bool; - default = null; - description = "Ignore errors reading directories."; - }; - ignoreUnknownTypes = lib.mkOption { - type = lib.types.nullOr lib.types.bool; - default = null; - description = "Ignore unknown file types."; - }; - }; + retention = { + keepLatest = lib.mkOption { + type = lib.types.int; + default = 5; + description = "Number of latest snapshots to keep."; + }; + keepHourly = lib.mkOption { + type = lib.types.int; + default = 48; + description = "Number of hourly snapshots to keep."; + }; + keepDaily = lib.mkOption { + type = lib.types.int; + default = 7; + description = "Number of daily snapshots to keep."; + }; + keepWeekly = lib.mkOption { + type = lib.types.int; + default = 4; + description = "Number of weekly snapshots to keep."; + }; + keepMonthly = lib.mkOption { + type = lib.types.int; + default = 3; + description = "Number of monthly snapshots to keep."; + }; + keepAnnual = lib.mkOption { + type = lib.types.int; + default = 0; + description = "Number of yearly snapshots to keep."; + }; + }; - compression = { - compressorName = lib.mkOption { - type = compressionType; - default = "none"; - description = "Name of the compressor to use."; - }; + files = { + ignoreDotFiles = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ + ".gitignore" + ".kopiaignore" + ]; + description = "List of files to source ignore lists from."; + }; + noParentDotFiles = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + default = false; + description = "Do not use parent ignore dot files."; + }; + ignoreCacheDirs = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + default = false; + description = "Ignore cache directories."; + }; + maxFileSize = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + description = "Maximum file size to include in backup."; + }; + oneFileSystem = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + default = null; + description = "Stay in parent filesystem when finding files."; + }; + }; - onlyCompress = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - description = "List of file extensions to compress."; - }; + errorHandling = { + ignoreFileErrors = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + default = null; + description = "Ignore errors reading ignore files."; + }; + ignoreDirectoryErrors = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + default = null; + description = "Ignore errors reading directories."; + }; + ignoreUnknownTypes = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + default = null; + description = "Ignore unknown file types."; + }; + }; - noParentOnlyCompress = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Do not use parent only compress list."; - }; + compression = { + compressorName = lib.mkOption { + type = compressionType; + default = "none"; + description = "Name of the compressor to use."; + }; - neverCompress = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - description = "List of file extensions to never compress."; - }; + onlyCompress = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "List of file extensions to compress."; + }; - noParentNeverCompress = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Do not use parent never compress list."; - }; + noParentOnlyCompress = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Do not use parent only compress list."; + }; - minSize = lib.mkOption { - type = lib.types.int; - default = 0; - description = "Minimum file size to compress."; - }; + neverCompress = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "List of file extensions to never compress."; + }; - maxSize = lib.mkOption { - type = lib.types.int; - default = 0; - description = "Maximum file size to compress."; - }; - }; + noParentNeverCompress = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Do not use parent never compress list."; + }; - metadataCompression = { - compressorName = lib.mkOption { - type = compressionType; - default = "zstd-fastest"; - description = "Name of the compressor to use."; - }; - }; + minSize = lib.mkOption { + type = lib.types.int; + default = 0; + description = "Minimum file size to compress."; + }; - splitter = { - algorithm = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - description = "Name of the splitter algorithm to use."; - }; - }; + maxSize = lib.mkOption { + type = lib.types.int; + default = 0; + description = "Maximum file size to compress."; + }; + }; - # FIXME: add action definition afterward (maybe implement it during implement at zfs, btrfs snapshot) + metadataCompression = { + compressorName = lib.mkOption { + type = compressionType; + default = "zstd-fastest"; + description = "Name of the compressor to use."; + }; + }; - osSnapshots = { - volumeShadowCopy = { - enable = lib.mkOption { - type = lib.types.nullOr ( - lib.types.enum [ - "never" - "always" - "when-available" - "inherit" - ] - ); - default = null; - description = "Enable volume shadow copy"; - }; - }; - }; + splitter = { + algorithm = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Name of the splitter algorithm to use."; + }; + }; + + # FIXME: add action definition afterward (maybe implement it during implement at zfs, btrfs snapshot) - logging = { - directories = { - snapshotted = lib.mkOption { - type = lib.types.nullOr lib.types.int; - default = null; - description = "Log detail when a directory is snapshotted"; - }; - ignored = lib.mkOption { - type = lib.types.nullOr lib.types.int; - default = null; - description = "Log detail when a directory is ignored"; - }; - }; + osSnapshots = { + volumeShadowCopy = { + enable = lib.mkOption { + type = lib.types.nullOr ( + lib.types.enum [ + "never" + "always" + "when-available" + "inherit" + ] + ); + default = null; + description = "Enable volume shadow copy"; + }; + }; + }; - entries = { - snapshotted = lib.mkOption { - type = lib.types.nullOr lib.types.int; - default = null; - description = "Log detail when an entry is snapshotted"; - }; - ignored = lib.mkOption { - type = lib.types.nullOr lib.types.int; - default = null; - description = "Log detail when an entry is ignored"; - }; - }; + logging = { + directories = { + snapshotted = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + description = "Log detail when a directory is snapshotted"; }; + ignored = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + description = "Log detail when a directory is ignored"; + }; + }; - upload = { - # maxParallelSnapshots - GUI only - maxParallelFileReads = lib.mkOption { - type = lib.types.nullOr lib.types.int; - default = null; - description = "Maximum number of parallel file reads(GUI Only)"; - }; - parallelUploadAboveSize = lib.mkOption { - type = lib.types.nullOr lib.types.int; - default = null; - description = "Use parallel uploads above size(GUI Only)"; - }; + entries = { + snapshotted = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + description = "Log detail when an entry is snapshotted"; + }; + ignored = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + description = "Log detail when an entry is ignored"; }; }; - } - ); - default = null; + }; + + upload = { + # maxParallelSnapshots - GUI only + maxParallelFileReads = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + description = "Maximum number of parallel file reads(GUI Only)"; + }; + parallelUploadAboveSize = lib.mkOption { + type = lib.types.nullOr lib.types.int; + default = null; + description = "Use parallel uploads above size(GUI Only)"; + }; + }; + }; }; instanceType = lib.types.submodule { options = { - policy = policyType; + policy = policyListType; }; }; @@ -252,18 +263,24 @@ let # generate policy name for policy file generation mkPolicyName = user: hostname: path: - "${user}@${hostname}${if path != "" then ":${path}" else ""}"; + "${user}@${hostname}${if path != null then ":${path}" else ""}"; mkPolicyFile = policy: (jsonFormat.generate "kopia-policy.json" policy); mkInstancePolicyService = name: instance: let - policyName = mkPolicyName instance.user config.networking.hostName instance.path; - policyFile = mkPolicyFile ( - { - "${policyName}" = instance.policy; + policies = lib.lists.foldr ( + policy: a: + a + // { + "${mkPolicyName instance.user config.networking.hostName policy.path}" = lib.attrsets.filterAttrs ( + n: v: n != "path" + ) policy; } + ) { } instance.policy; + policyFile = mkPolicyFile ( + policies // lib.optionalAttrs (config.services.kopia.globalPolicy != null) { "(global)" = config.services.kopia.globalPolicy; } @@ -275,6 +292,7 @@ let wantedBy = [ "kopia-snapshot-${name}.service" ]; after = [ "kopia-repository-${name}.service" ]; before = [ "kopia-snapshot-${name}.service" ]; + restartTriggers = [ policyFile ]; script = '' ${pkgs.kopia}/bin/kopia policy import --from-file=${policyFile} ''; |
