{ config, pkgs, ... }:
with pkgs.lib;
let
cfg = config.services.tarsnap;
optionalNullStr = e: v: if e == null then "" else v;
configFile = pkgs.writeText "tarsnap.conf" ''
cachedir ${cfg.cachedir}
keyfile ${cfg.keyfile}
${optionalString cfg.nodump "nodump"}
${optionalString cfg.printStats "print-stats"}
${optionalNullStr cfg.checkpointBytes "checkpoint-bytes "+cfg.checkpointBytes}
${optionalString cfg.aggressiveNetworking "aggressive-networking"}
${concatStringsSep "\n" (map (v: "exclude "+v) cfg.excludes)}
${concatStringsSep "\n" (map (v: "include "+v) cfg.includes)}
${optionalString cfg.lowmem "lowmem"}
${optionalString cfg.verylowmem "verylowmem"}
'';
in
{
options = {
services.tarsnap = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
If enabled, NixOS will periodically create backups of the
specified directories using the tarsnap
backup service. This installs a systemd
service called tarsnap-backup which is
periodically run by cron, or you may run it on-demand.
'';
};
label = mkOption {
type = types.str;
default = "nixos";
description = ''
Specifies the label for archives created by Tarsnap. The
full name will be
label-$(date+"%Y%m%d%H%M%S"). For
example, by default your backups will look similar to
nixos-20140301021501.
'';
};
cachedir = mkOption {
type = 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
cachedir 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
tarsnap --fsck to regenerate the cache
directory.
'';
};
keyfile = mkOption {
type = types.path;
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 tarsnap-keygen utility, and providing
your Tarsnap login credentials.
'';
};
nodump = mkOption {
type = types.bool;
default = true;
description = ''
If set to true, then don't archive files
which have the nodump flag set.
'';
};
printStats = mkOption {
type = types.bool;
default = true;
description = "Print statistics when creating archives.";
};
checkpointBytes = mkOption {
type = types.nullOr types.str;
default = "1G";
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,
checkpointBytes must be 1GB.
Can also be set to null to disable
checkpointing.
'';
};
period = mkOption {
type = types.str;
default = "15 01 * * *";
description = ''
This option defines (in the format used by cron) when
tarsnap is run for backups. The default is to update at
01:15 at night every day.
'';
};
aggressiveNetworking = mkOption {
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.
'';
};
directories = mkOption {
type = types.listOf types.path;
default = [];
description = "List of filesystem paths to archive.";
};
excludes = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Exclude files and directories matching the specified patterns.
'';
};
includes = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Include only files and directories matching the specified patterns.
Note that exclusions specified via
excludes take precedence over inclusions.
'';
};
lowmem = mkOption {
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.
'';
};
verylowmem = mkOption {
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
lowmem option does.
'';
};
};
};
config = mkIf cfg.enable {
assertions =
[ { assertion = cfg.directories != [];
message = "Must specify directories for Tarsnap to back up";
}
{ assertion = cfg.lowmem -> !cfg.verylowmem && (cfg.verylowmem -> !cfg.lowmem);
message = "You cannot set both lowmem and verylowmem";
}
];
systemd.services.tarsnap-backup = {
description = "Tarsnap Backup process";
path = [ pkgs.tarsnap pkgs.coreutils ];
script = ''
mkdir -p -m 0755 $(dirname ${cfg.cachedir})
mkdir -p -m 0600 ${cfg.cachedir}
exec tarsnap --configfile ${configFile} -c -f ${cfg.label}-$(date +"%Y%m%d%H%M%S") ${concatStringsSep " " cfg.directories}
'';
};
services.cron.systemCronJobs = optional cfg.enable
"${cfg.period} root ${config.systemd.package}/bin/systemctl start tarsnap-backup.service";
environment.systemPackages = [ pkgs.tarsnap ];
};
}