aboutsummaryrefslogtreecommitdiff
path: root/modules/backup/policy.nix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/backup/policy.nix')
-rw-r--r--modules/backup/policy.nix410
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}
'';