nixpkgs/nixos/modules/services/misc/snapper.nix
Christian Kögler e8a8f1233a snapper: add nixos module
fixes #27154
2017-07-16 10:06:42 +01:00

153 lines
3.9 KiB
Nix

{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.snapper;
in
{
options.services.snapper = {
snapshotInterval = mkOption {
type = types.str;
default = "hourly";
description = ''
Snapshot interval.
The format is described in
<citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry>.
'';
};
cleanupInterval = mkOption {
type = types.str;
default = "1d";
description = ''
Cleanup interval.
The format is described in
<citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry>.
'';
};
filters = mkOption {
type = types.nullOr types.lines;
default = null;
description = ''
Global display difference filter. See man:snapper(8) for more details.
'';
};
configs = mkOption {
default = { };
example = literalExample {
"home" = {
subvolume = "/home";
extraConfig = ''
ALLOW_USERS="alice"
'';
};
};
description = ''
Subvolume configuration
'';
type = types.attrsOf (types.submodule {
options = {
subvolume = mkOption {
type = types.path;
description = ''
Path of the subvolume or mount point.
This path is a subvolume and has to contain a subvolume named
.snapshots.
See also man:snapper(8) section PERMISSIONS.
'';
};
fstype = mkOption {
type = types.enum [ "btrfs" ];
default = "btrfs";
description = ''
Filesystem type. Only btrfs is stable and tested.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Additional configuration next to SUBVOLUME and FSTYPE.
See man:snapper-configs(5).
'';
};
};
});
};
};
config = mkIf (cfg.configs != {}) (let
documentation = [ "man:snapper(8)" "man:snapper-configs(5)" ];
in {
environment = {
systemPackages = [ pkgs.snapper ];
# Note: snapper/config-templates/default is only needed for create-config
# which is not the NixOS way to configure.
etc = {
"sysconfig/snapper".text = ''
SNAPPER_CONFIGS="${lib.concatStringsSep " " (builtins.attrNames cfg.configs)}"
'';
}
// (mapAttrs' (name: subvolume: nameValuePair "snapper/configs/${name}" ({
text = ''
${subvolume.extraConfig}
FSTYPE="${subvolume.fstype}"
SUBVOLUME="${subvolume.subvolume}"
'';
})) cfg.configs)
// (lib.optionalAttrs (cfg.filters != null) {
"snapper/filters/default.txt".text = cfg.filters;
});
};
services.dbus.packages = [ pkgs.snapper ];
systemd.services.snapper-timeline = {
description = "Timeline of Snapper Snapshots";
inherit documentation;
serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --timeline";
};
systemd.timers.snapper-timeline = {
description = "Timeline of Snapper Snapshots";
inherit documentation;
wantedBy = [ "basic.target" ];
timerConfig.OnCalendar = cfg.snapshotInterval;
};
systemd.services.snapper-cleanup = {
description = "Cleanup of Snapper Snapshots";
inherit documentation;
serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --cleanup";
};
systemd.timers.snapper-cleanup = {
description = "Cleanup of Snapper Snapshots";
inherit documentation;
wantedBy = [ "basic.target" ];
timerConfig.OnBootSec = "10m";
timerConfig.OnUnitActiveSec = cfg.cleanupInterval;
};
});
}