about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/services/backup
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-06-22 15:01:47 +0000
committerAlyssa Ross <hi@alyssa.is>2021-06-22 16:57:59 +0000
commit633cab0ecb07627706c6b523e219490f019eaab5 (patch)
tree4fb472bdfe2723037dad53dc1b8a87c939015f5e /nixpkgs/nixos/modules/services/backup
parentffb691c199e7e0cbc4e45e5310779c9e3f7c2a73 (diff)
parent432fc2d9a67f92e05438dff5fdc2b39d33f77997 (diff)
downloadnixlib-633cab0ecb07627706c6b523e219490f019eaab5.tar
nixlib-633cab0ecb07627706c6b523e219490f019eaab5.tar.gz
nixlib-633cab0ecb07627706c6b523e219490f019eaab5.tar.bz2
nixlib-633cab0ecb07627706c6b523e219490f019eaab5.tar.lz
nixlib-633cab0ecb07627706c6b523e219490f019eaab5.tar.xz
nixlib-633cab0ecb07627706c6b523e219490f019eaab5.tar.zst
nixlib-633cab0ecb07627706c6b523e219490f019eaab5.zip
Merge commit '432fc2d9a67f92e05438dff5fdc2b39d33f77997'
# Conflicts:
#	nixpkgs/pkgs/applications/editors/emacs/elisp-packages/elpa-generated.nix
#	nixpkgs/pkgs/applications/networking/mailreaders/thunderbird/default.nix
#	nixpkgs/pkgs/applications/window-managers/sway/default.nix
#	nixpkgs/pkgs/build-support/rust/default.nix
#	nixpkgs/pkgs/development/go-modules/generic/default.nix
Diffstat (limited to 'nixpkgs/nixos/modules/services/backup')
-rw-r--r--nixpkgs/nixos/modules/services/backup/duplicati.nix12
-rw-r--r--nixpkgs/nixos/modules/services/backup/duplicity.nix91
-rw-r--r--nixpkgs/nixos/modules/services/backup/mysql-backup.nix4
-rw-r--r--nixpkgs/nixos/modules/services/backup/postgresql-backup.nix2
-rw-r--r--nixpkgs/nixos/modules/services/backup/syncoid.nix16
5 files changed, 91 insertions, 34 deletions
diff --git a/nixpkgs/nixos/modules/services/backup/duplicati.nix b/nixpkgs/nixos/modules/services/backup/duplicati.nix
index 0ff720c5897d..cf5aebdecd28 100644
--- a/nixpkgs/nixos/modules/services/backup/duplicati.nix
+++ b/nixpkgs/nixos/modules/services/backup/duplicati.nix
@@ -54,11 +54,13 @@ in
       };
     };
 
-    users.users.duplicati = lib.optionalAttrs (cfg.user == "duplicati") {
-      uid = config.ids.uids.duplicati;
-      home = "/var/lib/duplicati";
-      createHome = true;
-      group = "duplicati";
+    users.users = lib.optionalAttrs (cfg.user == "duplicati") {
+      duplicati = {
+        uid = config.ids.uids.duplicati;
+        home = "/var/lib/duplicati";
+        createHome = true;
+        group = "duplicati";
+      };
     };
     users.groups.duplicati.gid = config.ids.gids.duplicati;
 
diff --git a/nixpkgs/nixos/modules/services/backup/duplicity.nix b/nixpkgs/nixos/modules/services/backup/duplicity.nix
index a8d564248623..1f6883ed02b7 100644
--- a/nixpkgs/nixos/modules/services/backup/duplicity.nix
+++ b/nixpkgs/nixos/modules/services/backup/duplicity.nix
@@ -1,16 +1,17 @@
-{ config, lib, pkgs, ...}:
+{ config, lib, pkgs, ... }:
 
 with lib;
-
 let
   cfg = config.services.duplicity;
 
   stateDirectory = "/var/lib/duplicity";
 
-  localTarget = if hasPrefix "file://" cfg.targetUrl
+  localTarget =
+    if hasPrefix "file://" cfg.targetUrl
     then removePrefix "file://" cfg.targetUrl else null;
 
-in {
+in
+{
   options.services.duplicity = {
     enable = mkEnableOption "backups with duplicity";
 
@@ -24,7 +25,7 @@ in {
 
     include = mkOption {
       type = types.listOf types.str;
-      default = [];
+      default = [ ];
       example = [ "/home" ];
       description = ''
         List of paths to include into the backups. See the FILE SELECTION
@@ -35,7 +36,7 @@ in {
 
     exclude = mkOption {
       type = types.listOf types.str;
-      default = [];
+      default = [ ];
       description = ''
         List of paths to exclude from backups. See the FILE SELECTION section in
         <citerefentry><refentrytitle>duplicity</refentrytitle>
@@ -82,14 +83,60 @@ in {
 
     extraFlags = mkOption {
       type = types.listOf types.str;
-      default = [];
-      example = [ "--full-if-older-than" "1M" ];
+      default = [ ];
+      example = [ "--backend-retry-delay" "100" ];
       description = ''
         Extra command-line flags passed to duplicity. See
         <citerefentry><refentrytitle>duplicity</refentrytitle>
         <manvolnum>1</manvolnum></citerefentry>.
       '';
     };
+
+    fullIfOlderThan = mkOption {
+      type = types.str;
+      default = "never";
+      example = "1M";
+      description = ''
+        If <literal>"never"</literal> (the default) always do incremental
+        backups (the first backup will be a full backup, of course).  If
+        <literal>"always"</literal> always do full backups.  Otherwise, this
+        must be a string representing a duration. Full backups will be made
+        when the latest full backup is older than this duration. If this is not
+        the case, an incremental backup is performed.
+      '';
+    };
+
+    cleanup = {
+      maxAge = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "6M";
+        description = ''
+          If non-null, delete all backup sets older than the given time.  Old backup sets
+          will not be deleted if backup sets newer than time depend on them.
+        '';
+      };
+      maxFull = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        example = 2;
+        description = ''
+          If non-null, delete all backups sets that are older than the count:th last full
+          backup (in other words, keep the last count full backups and
+          associated incremental sets).
+        '';
+      };
+      maxIncr = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        example = 1;
+        description = ''
+          If non-null, delete incremental sets of all backups sets that are
+          older than the count:th last full backup (in other words, keep only
+          old full backups and not their increments).
+        '';
+      };
+    };
   };
 
   config = mkIf cfg.enable {
@@ -99,18 +146,26 @@ in {
 
         environment.HOME = stateDirectory;
 
-        serviceConfig = {
-          ExecStart = ''
-            ${pkgs.duplicity}/bin/duplicity ${escapeShellArgs (
-              [
-                cfg.root
-                cfg.targetUrl
-                "--archive-dir" stateDirectory
-              ]
+        script =
+          let
+            target = escapeShellArg cfg.targetUrl;
+            extra = escapeShellArgs ([ "--archive-dir" stateDirectory ] ++ cfg.extraFlags);
+            dup = "${pkgs.duplicity}/bin/duplicity";
+          in
+          ''
+            set -x
+            ${dup} cleanup ${target} --force ${extra}
+            ${lib.optionalString (cfg.cleanup.maxAge != null) "${dup} remove-older-than ${lib.escapeShellArg cfg.cleanup.maxAge} ${target} --force ${extra}"}
+            ${lib.optionalString (cfg.cleanup.maxFull != null) "${dup} remove-all-but-n-full ${toString cfg.cleanup.maxFull} ${target} --force ${extra}"}
+            ${lib.optionalString (cfg.cleanup.maxIncr != null) "${dup} remove-all-incr-but-n-full ${toString cfg.cleanup.maxIncr} ${target} --force ${extra}"}
+            exec ${dup} ${if cfg.fullIfOlderThan == "always" then "full" else "incr"} ${lib.escapeShellArgs (
+              [ cfg.root cfg.targetUrl ]
               ++ concatMap (p: [ "--include" p ]) cfg.include
               ++ concatMap (p: [ "--exclude" p ]) cfg.exclude
-              ++ cfg.extraFlags)}
+              ++ (lib.optionals (cfg.fullIfOlderThan != "never" && cfg.fullIfOlderThan != "always") [ "--full-if-older-than" cfg.fullIfOlderThan ])
+              )} ${extra}
           '';
+        serviceConfig = {
           PrivateTmp = true;
           ProtectSystem = "strict";
           ProtectHome = "read-only";
@@ -130,7 +185,7 @@ in {
     assertions = singleton {
       # Duplicity will fail if the last file selection option is an include. It
       # is not always possible to detect but this simple case can be caught.
-      assertion = cfg.include != [] -> cfg.exclude != [] || cfg.extraFlags != [];
+      assertion = cfg.include != [ ] -> cfg.exclude != [ ] || cfg.extraFlags != [ ];
       message = ''
         Duplicity will fail if you only specify included paths ("Because the
         default is to include all files, the expression is redundant. Exiting
diff --git a/nixpkgs/nixos/modules/services/backup/mysql-backup.nix b/nixpkgs/nixos/modules/services/backup/mysql-backup.nix
index 506ded5e9e8c..9fca21002733 100644
--- a/nixpkgs/nixos/modules/services/backup/mysql-backup.nix
+++ b/nixpkgs/nixos/modules/services/backup/mysql-backup.nix
@@ -4,7 +4,7 @@ with lib;
 
 let
 
-  inherit (pkgs) mysql gzip;
+  inherit (pkgs) mariadb gzip;
 
   cfg = config.services.mysqlBackup;
   defaultUser = "mysqlbackup";
@@ -20,7 +20,7 @@ let
   '';
   backupDatabaseScript = db: ''
     dest="${cfg.location}/${db}.gz"
-    if ${mysql}/bin/mysqldump ${if cfg.singleTransaction then "--single-transaction" else ""} ${db} | ${gzip}/bin/gzip -c > $dest.tmp; then
+    if ${mariadb}/bin/mysqldump ${if cfg.singleTransaction then "--single-transaction" else ""} ${db} | ${gzip}/bin/gzip -c > $dest.tmp; then
       mv $dest.tmp $dest
       echo "Backed up to $dest"
     else
diff --git a/nixpkgs/nixos/modules/services/backup/postgresql-backup.nix b/nixpkgs/nixos/modules/services/backup/postgresql-backup.nix
index f4bd3aa447e5..9da2d522a68d 100644
--- a/nixpkgs/nixos/modules/services/backup/postgresql-backup.nix
+++ b/nixpkgs/nixos/modules/services/backup/postgresql-backup.nix
@@ -48,7 +48,7 @@ in {
 
       startAt = mkOption {
         default = "*-*-* 01:15:00";
-        type = types.str;
+        type = with types; either (listOf str) str;
         description = ''
           This option defines (see <literal>systemd.time</literal> for format) when the
           databases should be dumped.
diff --git a/nixpkgs/nixos/modules/services/backup/syncoid.nix b/nixpkgs/nixos/modules/services/backup/syncoid.nix
index e72e3fa59cf9..b764db1f14e4 100644
--- a/nixpkgs/nixos/modules/services/backup/syncoid.nix
+++ b/nixpkgs/nixos/modules/services/backup/syncoid.nix
@@ -197,14 +197,14 @@ in {
                ])) (attrValues cfg.commands);
         after = [ "zfs.target" ];
         serviceConfig = {
-          ExecStartPre = (map (pool: lib.escapeShellArgs [
-            "+/run/booted-system/sw/bin/zfs" "allow"
-            cfg.user "hold,send" pool
-          ]) (getPools "source")) ++
-          (map (pool: lib.escapeShellArgs [
-            "+/run/booted-system/sw/bin/zfs" "allow"
-            cfg.user "create,mount,receive,rollback" pool
-          ]) (getPools "target"));
+          ExecStartPre = let
+            allowCmd = permissions: pool: lib.escapeShellArgs [
+              "+/run/booted-system/sw/bin/zfs" "allow"
+              cfg.user (concatStringsSep "," permissions) pool
+            ];
+          in
+            (map (allowCmd [ "hold" "send" "snapshot" "destroy" ]) (getPools "source")) ++
+            (map (allowCmd [ "create" "mount" "receive" "rollback" ]) (getPools "target"));
           User = cfg.user;
           Group = cfg.group;
         };