nixos: refactor tarsnap backup service module
Major changes - Port to systemd timers: for each archive configuration is created a tarsnap@archive-name.timer which triggers the instanced service unit - Rename the `config` option to `archives` Minor/superficial improvements - Restrict tarsnap service capabilities - Use dirOf builtin - Set executable bit for owner of tarsnap cache directory - Set IOSchedulingClass to idle - Humanize numbers when printing stats - Rewrite most option descriptions - Simplify assertion
This commit is contained in:
parent
a869c8351c
commit
1bdd12ed69
@ -112,6 +112,9 @@ in zipModules ([]
|
|||||||
# VirtualBox
|
# VirtualBox
|
||||||
++ obsolete [ "services" "virtualbox" "enable" ] [ "services" "virtualboxGuest" "enable" ]
|
++ obsolete [ "services" "virtualbox" "enable" ] [ "services" "virtualboxGuest" "enable" ]
|
||||||
|
|
||||||
|
# Tarsnap
|
||||||
|
++ obsolete [ "services" "tarsnap" "config" ] [ "services" "tarsnap" "archives" ]
|
||||||
|
|
||||||
# proxy
|
# proxy
|
||||||
++ obsolete [ "nix" "proxy" ] [ "networking" "proxy" "default" ]
|
++ obsolete [ "nix" "proxy" ] [ "networking" "proxy" "default" ]
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ let
|
|||||||
keyfile ${config.services.tarsnap.keyfile}
|
keyfile ${config.services.tarsnap.keyfile}
|
||||||
${optionalString cfg.nodump "nodump"}
|
${optionalString cfg.nodump "nodump"}
|
||||||
${optionalString cfg.printStats "print-stats"}
|
${optionalString cfg.printStats "print-stats"}
|
||||||
|
${optionalString cfg.printStats "humanize-numbers"}
|
||||||
${optionalNullStr cfg.checkpointBytes "checkpoint-bytes "+cfg.checkpointBytes}
|
${optionalNullStr cfg.checkpointBytes "checkpoint-bytes "+cfg.checkpointBytes}
|
||||||
${optionalString cfg.aggressiveNetworking "aggressive-networking"}
|
${optionalString cfg.aggressiveNetworking "aggressive-networking"}
|
||||||
${concatStringsSep "\n" (map (v: "exclude "+v) cfg.excludes)}
|
${concatStringsSep "\n" (map (v: "exclude "+v) cfg.excludes)}
|
||||||
@ -27,46 +28,39 @@ in
|
|||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
If enabled, NixOS will periodically create backups of the
|
Enable periodic tarsnap backups.
|
||||||
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.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
keyfile = mkOption {
|
keyfile = mkOption {
|
||||||
type = types.path;
|
type = types.str;
|
||||||
default = "/root/tarsnap.key";
|
default = "/root/tarsnap.key";
|
||||||
description = ''
|
description = ''
|
||||||
Path to the keyfile which identifies the machine
|
The keyfile which associates this machine with your tarsnap
|
||||||
associated with your Tarsnap account. This file can
|
account.
|
||||||
be created using the
|
Create the keyfile with <command>tarsnap-keygen</command>.
|
||||||
<literal>tarsnap-keygen</literal> utility, and
|
|
||||||
providing your Tarsnap login credentials.
|
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 {
|
cachedir = mkOption {
|
||||||
type = types.path;
|
type = types.nullOr types.path;
|
||||||
default = "/var/cache/tarsnap";
|
default = "/var/cache/tarsnap";
|
||||||
description = ''
|
description = ''
|
||||||
Tarsnap operations use a "cache directory" which
|
The cache allows tarsnap to identify previously stored data
|
||||||
allows Tarsnap to identify which blocks of data have
|
blocks, reducing archival time and bandwidth usage.
|
||||||
been previously stored; this directory is specified
|
|
||||||
via the <literal>cachedir</literal> option. If the
|
Should the cache become desynchronized or corrupted, tarsnap
|
||||||
cache directory is lost or out of date, tarsnap
|
will refuse to run until you manually rebuild the cache with
|
||||||
creation/deletion operations will exit with an error
|
<command>tarsnap --fsck</command>.
|
||||||
message instructing you to run <literal>tarsnap
|
|
||||||
--fsck</literal> to regenerate the cache directory.
|
Set to <literal>null</literal> to disable caching.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkOption {
|
archives = mkOption {
|
||||||
type = types.attrsOf (types.submodule (
|
type = types.attrsOf (types.submodule (
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
@ -74,41 +68,44 @@ in
|
|||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
description = ''
|
description = ''
|
||||||
If set to <literal>true</literal>, then don't
|
Exclude files with the <literal>nodump</literal> flag.
|
||||||
archive files which have the
|
|
||||||
<literal>nodump</literal> flag set.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
printStats = mkOption {
|
printStats = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = true;
|
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 {
|
checkpointBytes = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = "1G";
|
default = "1GB";
|
||||||
description = ''
|
description = ''
|
||||||
Create a checkpoint per a particular amount of
|
Create a checkpoint every <literal>checkpointBytes</literal>
|
||||||
uploaded data. By default, Tarsnap will create
|
of uploaded data (optionally specified using an SI prefix).
|
||||||
checkpoints once per GB of data uploaded. At
|
|
||||||
minimum, <literal>checkpointBytes</literal> must be
|
|
||||||
1GB.
|
|
||||||
|
|
||||||
Can also be set to <literal>null</literal> to
|
1GB is the minimum value. A higher value is recommended,
|
||||||
disable checkpointing.
|
as checkpointing is expensive.
|
||||||
|
|
||||||
|
Set to <literal>null</literal> to disable checkpointing.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
period = mkOption {
|
period = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "15 01 * * *";
|
default = "01:15";
|
||||||
|
example = "hourly";
|
||||||
description = ''
|
description = ''
|
||||||
This option defines (in the format used by cron)
|
Create archive at this interval.
|
||||||
when tarsnap is run for backups. The default is to
|
|
||||||
backup the specified paths at 01:15 at night every
|
The format is described in
|
||||||
day.
|
<citerefentry><refentrytitle>systemd.time</refentrytitle>
|
||||||
|
<manvolnum>7</manvolnum></citerefentry>.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,11 +113,11 @@ in
|
|||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
Aggressive network behaviour: Use multiple TCP
|
Upload data over multiple TCP connections, potentially
|
||||||
connections when writing archives. Use of this
|
increasing tarsnap's bandwidth utilisation at the cost
|
||||||
option is recommended only in cases where TCP
|
of slowing down all other network traffic. Not
|
||||||
congestion control is known to be the limiting
|
recommended unless TCP congestion is the dominant
|
||||||
factor in upload performance.
|
limiting factor.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,8 +131,7 @@ in
|
|||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [];
|
default = [];
|
||||||
description = ''
|
description = ''
|
||||||
Exclude files and directories matching the specified
|
Exclude files and directories matching these patterns.
|
||||||
patterns.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -143,12 +139,10 @@ in
|
|||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [];
|
default = [];
|
||||||
description = ''
|
description = ''
|
||||||
Include only files and directories matching the
|
Include only files and directories matching these
|
||||||
specified patterns.
|
patterns (the empty list includes everything).
|
||||||
|
|
||||||
Note that exclusions specified via
|
Exclusions have precedence over inclusions.
|
||||||
<literal>excludes</literal> take precedence over
|
|
||||||
inclusions.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -156,10 +150,10 @@ in
|
|||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
Attempt to reduce tarsnap memory consumption. This
|
Reduce memory consumption by not caching small files.
|
||||||
option will slow down the process of creating
|
Possibly beneficial if the average file size is smaller
|
||||||
archives, but may help on systems where the average
|
than 1 MB and the number of files is lower than the
|
||||||
size of files being backed up is less than 1 MB.
|
total amount of RAM in KB.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -167,11 +161,9 @@ in
|
|||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
Try even harder to reduce tarsnap memory
|
Reduce memory consumption by a factor of 2 beyond what
|
||||||
consumption. This can significantly slow down
|
<literal>lowmem</literal> does, at the cost of significantly
|
||||||
tarsnap, but reduces its memory usage by an
|
slowing down the archiving process.
|
||||||
additional factor of 2 beyond what the
|
|
||||||
<literal>lowmem</literal> option does.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -188,25 +180,22 @@ in
|
|||||||
|
|
||||||
gamedata =
|
gamedata =
|
||||||
{ directories = [ "/var/lib/minecraft "];
|
{ directories = [ "/var/lib/minecraft "];
|
||||||
period = "*/30 * * * *";
|
period = "*:30";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
description = ''
|
description = ''
|
||||||
Configuration of a Tarsnap archive. In the example, your
|
Tarsnap archive configurations. Each attribute names an archive
|
||||||
machine will have two tarsnap archives:
|
to be created at a given time interval, according to the options
|
||||||
<literal>gamedata</literal> (backed up every 30 minutes) and
|
associated with it. When uploading to the tarsnap server,
|
||||||
<literal>nixos</literal> (backed up at 1:15 AM every night by
|
archive names are suffixed by a 1 second resolution timestamp.
|
||||||
default). You can control individual archive backups using
|
|
||||||
<literal>systemctl</literal>, using the
|
For each member of the set is created a timer which triggers the
|
||||||
<literal>tarsnap@nixos</literal> or
|
instanced <literal>tarsnap@</literal> service unit. You may use
|
||||||
<literal>tarsnap@gamedata</literal> units. For example,
|
<command>systemctl start tarsnap@archive-name</command> to
|
||||||
<literal>systemctl start tarsnap@nixos</literal> will
|
manually trigger creation of <literal>archive-name</literal> at
|
||||||
immediately create a new NixOS archive. By default, archives
|
any time.
|
||||||
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.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -216,38 +205,45 @@ in
|
|||||||
assertions =
|
assertions =
|
||||||
(mapAttrsToList (name: cfg:
|
(mapAttrsToList (name: cfg:
|
||||||
{ assertion = cfg.directories != [];
|
{ assertion = cfg.directories != [];
|
||||||
message = "Must specify directories for Tarsnap to back up";
|
message = "Must specify paths for tarsnap to back up";
|
||||||
}) cfg.config) ++
|
}) cfg.archives) ++
|
||||||
(mapAttrsToList (name: cfg:
|
(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";
|
message = "You cannot set both lowmem and verylowmem";
|
||||||
}) cfg.config);
|
}) cfg.archives);
|
||||||
|
|
||||||
systemd.services."tarsnap@" = {
|
systemd.services."tarsnap@" = {
|
||||||
description = "Tarsnap Backup of '%i'";
|
description = "Tarsnap archive '%i'";
|
||||||
requires = [ "network.target" ];
|
requires = [ "network.target" ];
|
||||||
|
|
||||||
path = [ pkgs.tarsnap pkgs.coreutils ];
|
path = [ pkgs.tarsnap pkgs.coreutils ];
|
||||||
scriptArgs = "%i";
|
scriptArgs = "%i";
|
||||||
script = ''
|
script = ''
|
||||||
mkdir -p -m 0755 $(dirname ${cfg.cachedir})
|
mkdir -p -m 0755 ${dirOf cfg.cachedir}
|
||||||
mkdir -p -m 0600 ${cfg.cachedir}
|
mkdir -p -m 0700 ${cfg.cachedir}
|
||||||
DIRS=`cat /etc/tarsnap/$1.dirs`
|
DIRS=`cat /etc/tarsnap/$1.dirs`
|
||||||
exec tarsnap --configfile /etc/tarsnap/$1.conf -c -f $1-$(date +"%Y%m%d%H%M%S") $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:
|
systemd.timers = mapAttrs' (name: cfg: nameValuePair "tarsnap@${name}"
|
||||||
"${cfg.period} root ${config.systemd.package}/bin/systemctl start tarsnap@${name}"
|
{ timerConfig.OnCalendar = cfg.period;
|
||||||
) cfg.config;
|
wantedBy = [ "timers.target" ];
|
||||||
|
}) cfg.archives;
|
||||||
|
|
||||||
environment.etc =
|
environment.etc =
|
||||||
(mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.conf"
|
(mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.conf"
|
||||||
{ text = configFile cfg;
|
{ text = configFile cfg;
|
||||||
}) cfg.config) //
|
}) cfg.archives) //
|
||||||
(mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.dirs"
|
(mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.dirs"
|
||||||
{ text = concatStringsSep " " cfg.directories;
|
{ text = concatStringsSep " " cfg.directories;
|
||||||
}) cfg.config);
|
}) cfg.archives);
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.tarsnap ];
|
environment.systemPackages = [ pkgs.tarsnap ];
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user