diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 76620f1d02a..94c1667d39d 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -78,8 +78,9 @@
./services/backup/bacula.nix
./services/backup/mysql-backup.nix
./services/backup/postgresql-backup.nix
- ./services/backup/sitecopy-backup.nix
./services/backup/rsnapshot.nix
+ ./services/backup/sitecopy-backup.nix
+ ./services/backup/tarsnap.nix
./services/databases/4store-endpoint.nix
./services/databases/4store.nix
./services/databases/couchdb.nix
diff --git a/nixos/modules/services/backup/tarsnap.nix b/nixos/modules/services/backup/tarsnap.nix
new file mode 100644
index 00000000000..3395a0b5263
--- /dev/null
+++ b/nixos/modules/services/backup/tarsnap.nix
@@ -0,0 +1,200 @@
+{ 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 ];
+ };
+}