nixos: refactor tarsnap module
The Tarsnap module is now far more flexible, allowing individual archives with individual options to be specified at will, allowing granular backup schedules, etc. Signed-off-by: Austin Seipp <aseipp@pobox.com>
This commit is contained in:
parent
7faaa9e6da
commit
9242ed1fe2
@ -7,9 +7,9 @@ let
|
|||||||
|
|
||||||
optionalNullStr = e: v: if e == null then "" else v;
|
optionalNullStr = e: v: if e == null then "" else v;
|
||||||
|
|
||||||
configFile = pkgs.writeText "tarsnap.conf" ''
|
configFile = cfg: ''
|
||||||
cachedir ${cfg.cachedir}
|
cachedir ${config.services.tarsnap.cachedir}
|
||||||
keyfile ${cfg.keyfile}
|
keyfile ${config.services.tarsnap.keyfile}
|
||||||
${optionalString cfg.nodump "nodump"}
|
${optionalString cfg.nodump "nodump"}
|
||||||
${optionalString cfg.printStats "print-stats"}
|
${optionalString cfg.printStats "print-stats"}
|
||||||
${optionalNullStr cfg.checkpointBytes "checkpoint-bytes "+cfg.checkpointBytes}
|
${optionalNullStr cfg.checkpointBytes "checkpoint-bytes "+cfg.checkpointBytes}
|
||||||
@ -39,15 +39,15 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
label = mkOption {
|
keyfile = mkOption {
|
||||||
type = types.str;
|
type = types.path;
|
||||||
default = "nixos";
|
default = "/root/tarsnap.key";
|
||||||
description = ''
|
description = ''
|
||||||
Specifies the label for archives created by Tarsnap. The
|
Path to the keyfile which identifies the machine
|
||||||
full name will be
|
associated with your Tarsnap account. This file can
|
||||||
<literal>label-$(date+"%Y%m%d%H%M%S")</literal>. For
|
be created using the
|
||||||
example, by default your backups will look similar to
|
<literal>tarsnap-keygen</literal> utility, and
|
||||||
<literal>nixos-20140301011501</literal>.
|
providing your Tarsnap login credentials.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,122 +55,158 @@ in
|
|||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/cache/tarsnap";
|
default = "/var/cache/tarsnap";
|
||||||
description = ''
|
description = ''
|
||||||
Tarsnap operations use a "cache directory" which allows
|
Tarsnap operations use a "cache directory" which
|
||||||
Tarsnap to identify which blocks of data have been
|
allows Tarsnap to identify which blocks of data have
|
||||||
previously stored; this directory is specified via the
|
been previously stored; this directory is specified
|
||||||
<literal>cachedir</literal> option. If the cache directory
|
via the <literal>cachedir</literal> option. If the
|
||||||
is lost or out of date, tarsnap creation/deletion operations
|
cache directory is lost or out of date, tarsnap
|
||||||
will exit with an error message instructing you to run
|
creation/deletion operations will exit with an error
|
||||||
<literal>tarsnap --fsck</literal> to regenerate the cache
|
message instructing you to run <literal>tarsnap
|
||||||
directory.
|
--fsck</literal> to regenerate the cache directory.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
keyfile = mkOption {
|
config = mkOption {
|
||||||
type = types.path;
|
type = types.attrsOf (types.submodule (
|
||||||
default = "/root/tarsnap.key";
|
{
|
||||||
description = ''
|
options = {
|
||||||
Path to the keyfile which identifies the machine associated
|
nodump = mkOption {
|
||||||
with your Tarsnap account. This file can be created using
|
type = types.bool;
|
||||||
the <literal>tarsnap-keygen</literal> utility, and providing
|
default = true;
|
||||||
your Tarsnap login credentials.
|
description = ''
|
||||||
|
If set to <literal>true</literal>, then don't
|
||||||
|
archive files which have the
|
||||||
|
<literal>nodump</literal> 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, <literal>checkpointBytes</literal> must be
|
||||||
|
1GB.
|
||||||
|
|
||||||
|
Can also be set to <literal>null</literal> 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
|
||||||
|
backup the specified paths 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
|
||||||
|
<literal>excludes</literal> 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
|
||||||
|
<literal>lowmem</literal> option does.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
default = {};
|
||||||
|
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
nixos =
|
||||||
|
{ directories = [ "/home" "/root/ssl" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
gamedata =
|
||||||
|
{ directories = [ "/var/lib/minecraft "];
|
||||||
|
period = "*/30 * * * *";
|
||||||
|
};
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
};
|
|
||||||
|
|
||||||
nodump = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
description = ''
|
||||||
If set to <literal>true</literal>, then don't archive files
|
Configuration of a Tarsnap archive. In the example, your
|
||||||
which have the <literal>nodump</literal> flag set.
|
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
|
||||||
printStats = mkOption {
|
<literal>systemctl</literal>, using the
|
||||||
type = types.bool;
|
<literal>tarsnap@nixos</literal> or
|
||||||
default = true;
|
<literal>tarsnap@gamedata</literal> units. For example,
|
||||||
description = "Print statistics when creating archives.";
|
<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,
|
||||||
checkpointBytes = mkOption {
|
down to second resolution. This means you can use GNU
|
||||||
type = types.nullOr types.str;
|
<literal>sort</literal> to sort output easily.
|
||||||
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,
|
|
||||||
<literal>checkpointBytes</literal> must be 1GB.
|
|
||||||
|
|
||||||
Can also be set to <literal>null</literal> 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 backup the
|
|
||||||
specified paths 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
|
|
||||||
<literal>excludes</literal> 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
|
|
||||||
<literal>lowmem</literal> option does.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -178,26 +214,40 @@ in
|
|||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
assertions =
|
assertions =
|
||||||
[ { assertion = cfg.directories != [];
|
(mapAttrsToList (name: cfg:
|
||||||
|
{ assertion = cfg.directories != [];
|
||||||
message = "Must specify directories for Tarsnap to back up";
|
message = "Must specify directories for Tarsnap to back up";
|
||||||
}
|
}) cfg.config) ++
|
||||||
|
(mapAttrsToList (name: cfg:
|
||||||
{ assertion = cfg.lowmem -> !cfg.verylowmem && (cfg.verylowmem -> !cfg.lowmem);
|
{ assertion = cfg.lowmem -> !cfg.verylowmem && (cfg.verylowmem -> !cfg.lowmem);
|
||||||
message = "You cannot set both lowmem and verylowmem";
|
message = "You cannot set both lowmem and verylowmem";
|
||||||
}
|
}) cfg.config);
|
||||||
];
|
|
||||||
|
systemd.services."tarsnap@" = {
|
||||||
|
description = "Tarsnap Backup of '%i'";
|
||||||
|
requires = [ "network.target" ];
|
||||||
|
|
||||||
systemd.services.tarsnap-backup = {
|
|
||||||
description = "Tarsnap Backup process";
|
|
||||||
path = [ pkgs.tarsnap pkgs.coreutils ];
|
path = [ pkgs.tarsnap pkgs.coreutils ];
|
||||||
|
scriptArgs = "%i";
|
||||||
script = ''
|
script = ''
|
||||||
mkdir -p -m 0755 $(dirname ${cfg.cachedir})
|
mkdir -p -m 0755 $(dirname ${cfg.cachedir})
|
||||||
mkdir -p -m 0600 ${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}
|
DIRS=`cat /etc/tarsnap/$1.dirs`
|
||||||
|
exec tarsnap --configfile /etc/tarsnap/$1.conf -c -f $1-$(date +"%Y%m%d%H%M%S") $DIRS
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
services.cron.systemCronJobs = optional cfg.enable
|
services.cron.systemCronJobs = mapAttrsToList (name: cfg:
|
||||||
"${cfg.period} root ${config.systemd.package}/bin/systemctl start tarsnap-backup.service";
|
"${cfg.period} root ${config.systemd.package}/bin/systemctl start tarsnap@${name}"
|
||||||
|
) cfg.config;
|
||||||
|
|
||||||
|
environment.etc =
|
||||||
|
(mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.conf"
|
||||||
|
{ text = configFile cfg;
|
||||||
|
}) cfg.config) //
|
||||||
|
(mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.dirs"
|
||||||
|
{ text = concatStringsSep " " cfg.directories;
|
||||||
|
}) cfg.config);
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.tarsnap ];
|
environment.systemPackages = [ pkgs.tarsnap ];
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user