summary refs log tree commit diff
path: root/nixos/modules/services/backup/tarsnap.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services/backup/tarsnap.nix')
-rw-r--r--nixos/modules/services/backup/tarsnap.nix176
1 files changed, 86 insertions, 90 deletions
diff --git a/nixos/modules/services/backup/tarsnap.nix b/nixos/modules/services/backup/tarsnap.nix
index 1b0bcadca15..155161945cd 100644
--- a/nixos/modules/services/backup/tarsnap.nix
+++ b/nixos/modules/services/backup/tarsnap.nix
@@ -12,6 +12,7 @@ let
     keyfile  ${config.services.tarsnap.keyfile}
     ${optionalString cfg.nodump "nodump"}
     ${optionalString cfg.printStats "print-stats"}
+    ${optionalString cfg.printStats "humanize-numbers"}
     ${optionalNullStr cfg.checkpointBytes "checkpoint-bytes "+cfg.checkpointBytes}
     ${optionalString cfg.aggressiveNetworking "aggressive-networking"}
     ${concatStringsSep "\n" (map (v: "exclude "+v) cfg.excludes)}
@@ -27,46 +28,39 @@ in
         type = types.bool;
         default = false;
         description = ''
-          If enabled, NixOS will periodically create backups of the
-          specified directories using the <literal>tarsnap</literal>
-          backup service. This installs a <literal>systemd</literal>
-          service called <literal>tarsnap-backup</literal> which is
-          periodically run by cron, or you may run it on-demand.
-
-          See the Tarsnap <link
-          xlink:href='http://www.tarsnap.com/gettingstarted.html'>Getting
-          Started</link> page.
+          Enable periodic tarsnap backups.
         '';
       };
 
       keyfile = mkOption {
-        type = types.path;
+        type = types.str;
         default = "/root/tarsnap.key";
         description = ''
-          Path to the keyfile which identifies the machine
-          associated with your Tarsnap account. This file can
-          be created using the
-          <literal>tarsnap-keygen</literal> utility, and
-          providing your Tarsnap login credentials.
+          The keyfile which associates this machine with your tarsnap
+          account.
+          Create the keyfile with <command>tarsnap-keygen</command>.
+
+          The keyfile name should be given as a string and not a path, to
+          avoid the key being copied into the Nix store.
         '';
       };
 
       cachedir = mkOption {
-        type    = types.path;
+        type    = types.nullOr types.path;
         default = "/var/cache/tarsnap";
         description = ''
-          Tarsnap operations use a "cache directory" which
-          allows Tarsnap to identify which blocks of data have
-          been previously stored; this directory is specified
-          via the <literal>cachedir</literal> option. If the
-          cache directory is lost or out of date, tarsnap
-          creation/deletion operations will exit with an error
-          message instructing you to run <literal>tarsnap
-          --fsck</literal> to regenerate the cache directory.
+          The cache allows tarsnap to identify previously stored data
+          blocks, reducing archival time and bandwidth usage.
+
+          Should the cache become desynchronized or corrupted, tarsnap
+          will refuse to run until you manually rebuild the cache with
+          <command>tarsnap --fsck</command>.
+
+          Set to <literal>null</literal> to disable caching.
         '';
       };
 
-      config = mkOption {
+      archives = mkOption {
         type = types.attrsOf (types.submodule (
           {
             options = {
@@ -74,41 +68,44 @@ in
                 type = types.bool;
                 default = true;
                 description = ''
-                  If set to <literal>true</literal>, then don't
-                  archive files which have the
-                  <literal>nodump</literal> flag set.
+                  Exclude files with the <literal>nodump</literal> flag.
                 '';
               };
 
               printStats = mkOption {
                 type = types.bool;
                 default = true;
-                description = "Print statistics when creating archives.";
+                description = ''
+                  Print global archive statistics upon completion.
+                  The output is available via
+                  <command>systemctl status tarsnap@archive-name</command>.
+                '';
               };
 
               checkpointBytes = mkOption {
                 type = types.nullOr types.str;
-                default = "1G";
+                default = "1GB";
                 description = ''
-                  Create a checkpoint per a particular amount of
-                  uploaded data. By default, Tarsnap will create
-                  checkpoints once per GB of data uploaded. At
-                  minimum, <literal>checkpointBytes</literal> must be
-                  1GB.
-
-                  Can also be set to <literal>null</literal> to
-                  disable checkpointing.
+                  Create a checkpoint every <literal>checkpointBytes</literal>
+                  of uploaded data (optionally specified using an SI prefix).
+
+                  1GB is the minimum value. A higher value is recommended,
+                  as checkpointing is expensive.
+
+                  Set to <literal>null</literal> to disable checkpointing.
                 '';
               };
 
               period = mkOption {
                 type = types.str;
-                default = "15 01 * * *";
+                default = "01:15";
+                example = "hourly";
                 description = ''
-                  This option defines (in the format used by cron)
-                  when tarsnap is run for backups. The default is to
-                  backup the specified paths at 01:15 at night every
-                  day.
+                  Create archive at this interval.
+
+                  The format is described in
+                  <citerefentry><refentrytitle>systemd.time</refentrytitle>
+                  <manvolnum>7</manvolnum></citerefentry>.
                 '';
               };
 
@@ -116,11 +113,11 @@ in
                 type = types.bool;
                 default = false;
                 description = ''
-                  Aggressive network behaviour: Use multiple TCP
-                  connections when writing archives.  Use of this
-                  option is recommended only in cases where TCP
-                  congestion control is known to be the limiting
-                  factor in upload performance.
+                  Upload data over multiple TCP connections, potentially
+                  increasing tarsnap's bandwidth utilisation at the cost
+                  of slowing down all other network traffic. Not
+                  recommended unless TCP congestion is the dominant
+                  limiting factor.
                 '';
               };
 
@@ -134,8 +131,7 @@ in
                 type = types.listOf types.str;
                 default = [];
                 description = ''
-                  Exclude files and directories matching the specified
-                  patterns.
+                  Exclude files and directories matching these patterns.
                 '';
               };
 
@@ -143,12 +139,10 @@ in
                 type = types.listOf types.str;
                 default = [];
                 description = ''
-                  Include only files and directories matching the
-                  specified patterns.
+                  Include only files and directories matching these
+                  patterns (the empty list includes everything).
 
-                  Note that exclusions specified via
-                  <literal>excludes</literal> take precedence over
-                  inclusions.
+                  Exclusions have precedence over inclusions.
                 '';
               };
 
@@ -156,10 +150,10 @@ in
                 type = types.bool;
                 default = false;
                 description = ''
-                  Attempt to reduce tarsnap memory consumption.  This
-                  option will slow down the process of creating
-                  archives, but may help on systems where the average
-                  size of files being backed up is less than 1 MB.
+                  Reduce memory consumption by not caching small files.
+                  Possibly beneficial if the average file size is smaller
+                  than 1 MB and the number of files is lower than the
+                  total amount of RAM in KB.
                 '';
               };
 
@@ -167,11 +161,9 @@ in
                 type = types.bool;
                 default = false;
                 description = ''
-                  Try even harder to reduce tarsnap memory
-                  consumption.  This can significantly slow down
-                  tarsnap, but reduces its memory usage by an
-                  additional factor of 2 beyond what the
-                  <literal>lowmem</literal> option does.
+                  Reduce memory consumption by a factor of 2 beyond what
+                  <literal>lowmem</literal> does, at the cost of significantly
+                  slowing down the archiving process.
                 '';
               };
             };
@@ -188,25 +180,22 @@ in
 
             gamedata =
               { directories = [ "/var/lib/minecraft "];
-                period      = "*/30 * * * *";
+                period      = "*:30";
               };
           }
         '';
 
         description = ''
-          Configuration of a Tarsnap archive. In the example, your
-          machine will have two tarsnap archives:
-          <literal>gamedata</literal> (backed up every 30 minutes) and
-          <literal>nixos</literal> (backed up at 1:15 AM every night by
-          default). You can control individual archive backups using
-          <literal>systemctl</literal>, using the
-          <literal>tarsnap@nixos</literal> or
-          <literal>tarsnap@gamedata</literal> units. For example,
-          <literal>systemctl start tarsnap@nixos</literal> will
-          immediately create a new NixOS archive. By default, archives
-          are suffixed with the timestamp of when they were started,
-          down to second resolution. This means you can use GNU
-          <literal>sort</literal> to sort output easily.
+          Tarsnap archive configurations. Each attribute names an archive
+          to be created at a given time interval, according to the options
+          associated with it. When uploading to the tarsnap server,
+          archive names are suffixed by a 1 second resolution timestamp.
+
+          For each member of the set is created a timer which triggers the
+          instanced <literal>tarsnap@</literal> service unit. You may use
+          <command>systemctl start tarsnap@archive-name</command> to
+          manually trigger creation of <literal>archive-name</literal> at
+          any time.
         '';
       };
     };
@@ -216,38 +205,45 @@ in
     assertions =
       (mapAttrsToList (name: cfg:
         { assertion = cfg.directories != [];
-          message = "Must specify directories for Tarsnap to back up";
-        }) cfg.config) ++
+          message = "Must specify paths for tarsnap to back up";
+        }) cfg.archives) ++
       (mapAttrsToList (name: cfg:
-        { assertion = cfg.lowmem -> !cfg.verylowmem && (cfg.verylowmem -> !cfg.lowmem);
+        { assertion = !(cfg.lowmem && cfg.verylowmem);
           message = "You cannot set both lowmem and verylowmem";
-        }) cfg.config);
+        }) cfg.archives);
 
     systemd.services."tarsnap@" = {
-      description = "Tarsnap Backup of '%i'";
+      description = "Tarsnap archive '%i'";
       requires    = [ "network.target" ];
 
       path = [ pkgs.tarsnap pkgs.coreutils ];
       scriptArgs = "%i";
       script = ''
-        mkdir -p -m 0755 $(dirname ${cfg.cachedir})
-        mkdir -p -m 0600 ${cfg.cachedir}
+        mkdir -p -m 0755 ${dirOf cfg.cachedir}
+        mkdir -p -m 0700 ${cfg.cachedir}
         DIRS=`cat /etc/tarsnap/$1.dirs`
         exec tarsnap --configfile /etc/tarsnap/$1.conf -c -f $1-$(date +"%Y%m%d%H%M%S") $DIRS
       '';
+
+      serviceConfig = {
+        IOSchedulingClass = "idle";
+        NoNewPrivileges = "true";
+        CapabilityBoundingSet = "CAP_DAC_READ_SEARCH";
+      };
     };
 
-    services.cron.systemCronJobs = mapAttrsToList (name: cfg:
-      "${cfg.period} root ${config.systemd.package}/bin/systemctl start tarsnap@${name}"
-    ) cfg.config;
+    systemd.timers = mapAttrs' (name: cfg: nameValuePair "tarsnap@${name}"
+      { timerConfig.OnCalendar = cfg.period;
+        wantedBy = [ "timers.target" ];
+      }) cfg.archives;
 
     environment.etc =
       (mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.conf"
         { text = configFile cfg;
-        }) cfg.config) //
+        }) cfg.archives) //
       (mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.dirs"
         { text = concatStringsSep " " cfg.directories;
-        }) cfg.config);
+        }) cfg.archives);
 
     environment.systemPackages = [ pkgs.tarsnap ];
   };