nixos: Add ZFS auto-snapshotting module
This commit is contained in:
parent
5f0f47994a
commit
bb188bbba7
@ -11,18 +11,30 @@ with pkgs.lib;
|
|||||||
let
|
let
|
||||||
|
|
||||||
cfgSpl = config.boot.spl;
|
cfgSpl = config.boot.spl;
|
||||||
|
cfgSnapshots = config.services.zfs.autoSnapshot;
|
||||||
|
|
||||||
inInitrd = any (fs: fs == "zfs") config.boot.initrd.supportedFilesystems;
|
inInitrd = any (fs: fs == "zfs") config.boot.initrd.supportedFilesystems;
|
||||||
inSystem = any (fs: fs == "zfs") config.boot.supportedFilesystems;
|
inSystem = any (fs: fs == "zfs") config.boot.supportedFilesystems;
|
||||||
|
|
||||||
|
enableAutoSnapshots = cfgSnapshots.enable;
|
||||||
|
enableZfs = inInitrd || inSystem || enableAutoSnapshots;
|
||||||
|
|
||||||
kernel = config.boot.kernelPackages;
|
kernel = config.boot.kernelPackages;
|
||||||
|
|
||||||
|
autosnapPkg = pkgs.zfstools.override {
|
||||||
|
zfs = config.boot.kernelPackages.zfs;
|
||||||
|
};
|
||||||
|
|
||||||
|
zfsAutoSnap = "${autosnapPkg}/bin/zfs-auto-snapshot";
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
###### interface
|
###### interface
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
boot.spl.hostid = mkOption {
|
boot.spl.hostid = mkOption {
|
||||||
default = "";
|
default = "";
|
||||||
example = "0xdeadbeef";
|
example = "0xdeadbeef";
|
||||||
description = ''
|
description = ''
|
||||||
@ -34,62 +46,177 @@ in
|
|||||||
manually import pools.
|
manually import pools.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.zfs.autoSnapshot = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Enable the (OpenSolaris-compatible) ZFS auto-snapshotting service.
|
||||||
|
Note that you must set the <literal>com.sun:auto-snapshot</literal>
|
||||||
|
property to <literal>true</literal> on all datasets which you wish
|
||||||
|
to auto-snapshot.
|
||||||
|
|
||||||
|
You can override a child dataset to use, or not use auto-snapshotting
|
||||||
|
by setting its flag with the given interval:
|
||||||
|
<literal>zfs set com.sun:auto-snapshot:weekly=false DATASET</literal>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
frequent = mkOption {
|
||||||
|
default = 4;
|
||||||
|
type = types.int;
|
||||||
|
description = ''
|
||||||
|
Number of frequent (15-minute) auto-snapshots that you wish to keep.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
hourly = mkOption {
|
||||||
|
default = 24;
|
||||||
|
type = types.int;
|
||||||
|
description = ''
|
||||||
|
Number of hourly auto-snapshots that you wish to keep.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
daily = mkOption {
|
||||||
|
default = 7;
|
||||||
|
type = types.int;
|
||||||
|
description = ''
|
||||||
|
Number of daily auto-snapshots that you wish to keep.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
weekly = mkOption {
|
||||||
|
default = 4;
|
||||||
|
type = types.int;
|
||||||
|
description = ''
|
||||||
|
Number of weekly auto-snapshots that you wish to keep.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
monthly = mkOption {
|
||||||
|
default = 12;
|
||||||
|
type = types.int;
|
||||||
|
description = ''
|
||||||
|
Number of monthly auto-snapshots that you wish to keep.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
###### implementation
|
###### implementation
|
||||||
|
|
||||||
config = mkIf ( inInitrd || inSystem ) {
|
config = mkMerge [
|
||||||
|
(mkIf enableZfs {
|
||||||
boot = {
|
boot = {
|
||||||
kernelModules = [ "spl" "zfs" ] ;
|
kernelModules = [ "spl" "zfs" ] ;
|
||||||
extraModulePackages = [ kernel.zfs kernel.spl ];
|
extraModulePackages = [ kernel.zfs kernel.spl ];
|
||||||
extraModprobeConfig = mkIf (cfgSpl.hostid != "") ''
|
extraModprobeConfig = mkIf (cfgSpl.hostid != "") ''
|
||||||
options spl spl_hostid=${cfgSpl.hostid}
|
options spl spl_hostid=${cfgSpl.hostid}
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
boot.initrd = mkIf inInitrd {
|
|
||||||
kernelModules = [ "spl" "zfs" ] ;
|
|
||||||
extraUtilsCommands =
|
|
||||||
''
|
|
||||||
cp -v ${kernel.zfs}/sbin/zfs $out/bin
|
|
||||||
cp -v ${kernel.zfs}/sbin/zdb $out/bin
|
|
||||||
cp -v ${kernel.zfs}/sbin/zpool $out/bin
|
|
||||||
cp -pdv ${kernel.zfs}/lib/lib*.so* $out/lib
|
|
||||||
cp -pdv ${pkgs.zlib}/lib/lib*.so* $out/lib
|
|
||||||
'';
|
'';
|
||||||
postDeviceCommands =
|
|
||||||
''
|
|
||||||
zpool import -f -a
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services."zpool-import" = {
|
|
||||||
description = "Import zpools";
|
|
||||||
after = [ "systemd-udev-settle.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
restartIfChanged = false;
|
|
||||||
ExecStart = "${kernel.zfs}/sbin/zpool import -f -a";
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services."zfs-mount" = {
|
boot.initrd = mkIf inInitrd {
|
||||||
description = "Mount ZFS Volumes";
|
kernelModules = [ "spl" "zfs" ] ;
|
||||||
after = [ "zpool-import.service" ];
|
extraUtilsCommands =
|
||||||
wantedBy = [ "local-fs.target" ];
|
''
|
||||||
serviceConfig = {
|
cp -v ${kernel.zfs}/sbin/zfs $out/bin
|
||||||
Type = "oneshot";
|
cp -v ${kernel.zfs}/sbin/zdb $out/bin
|
||||||
RemainAfterExit = true;
|
cp -v ${kernel.zfs}/sbin/zpool $out/bin
|
||||||
restartIfChanged = false;
|
cp -pdv ${kernel.zfs}/lib/lib*.so* $out/lib
|
||||||
ExecStart = "${kernel.zfs}/sbin/zfs mount -a";
|
cp -pdv ${pkgs.zlib}/lib/lib*.so* $out/lib
|
||||||
ExecStop = "${kernel.zfs}/sbin/zfs umount -a";
|
'';
|
||||||
|
postDeviceCommands =
|
||||||
|
''
|
||||||
|
zpool import -f -a
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
system.fsPackages = [ kernel.zfs ]; # XXX: needed? zfs doesn't have (need) a fsck
|
systemd.services."zpool-import" = {
|
||||||
environment.systemPackages = [ kernel.zfs ];
|
description = "Import zpools";
|
||||||
services.udev.packages = [ kernel.zfs ]; # to hook zvol naming, etc.
|
after = [ "systemd-udev-settle.service" ];
|
||||||
};
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
ExecStart = "${kernel.zfs}/sbin/zpool import -f -a";
|
||||||
|
};
|
||||||
|
restartIfChanged = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."zfs-mount" = {
|
||||||
|
description = "Mount ZFS Volumes";
|
||||||
|
after = [ "zpool-import.service" ];
|
||||||
|
wantedBy = [ "local-fs.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
ExecStart = "${kernel.zfs}/sbin/zfs mount -a";
|
||||||
|
ExecStop = "${kernel.zfs}/sbin/zfs umount -a";
|
||||||
|
};
|
||||||
|
restartIfChanged = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
system.fsPackages = [ kernel.zfs ]; # XXX: needed? zfs doesn't have (need) a fsck
|
||||||
|
environment.systemPackages = [ kernel.zfs ];
|
||||||
|
services.udev.packages = [ kernel.zfs ]; # to hook zvol naming, etc.
|
||||||
|
})
|
||||||
|
|
||||||
|
(mkIf enableAutoSnapshots {
|
||||||
|
systemd.services."zfs-snapshot-frequent" = {
|
||||||
|
description = "ZFS auto-snapshotting every 15 mins";
|
||||||
|
after = [ "zpool-import.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${zfsAutoSnap} frequent ${toString cfgSnapshots.frequent}";
|
||||||
|
};
|
||||||
|
restartIfChanged = false;
|
||||||
|
startAt = "*:15,30,45";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."zfs-snapshot-hourly" = {
|
||||||
|
description = "ZFS auto-snapshotting every hour";
|
||||||
|
after = [ "zpool-import.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${zfsAutoSnap} hourly ${toString cfgSnapshots.hourly}";
|
||||||
|
};
|
||||||
|
restartIfChanged = false;
|
||||||
|
startAt = "hourly";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."zfs-snapshot-daily" = {
|
||||||
|
description = "ZFS auto-snapshotting every day";
|
||||||
|
after = [ "zpool-import.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${zfsAutoSnap} daily ${toString cfgSnapshots.daily}";
|
||||||
|
};
|
||||||
|
restartIfChanged = false;
|
||||||
|
startAt = "daily";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."zfs-snapshot-weekly" = {
|
||||||
|
description = "ZFS auto-snapshotting every week";
|
||||||
|
after = [ "zpool-import.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${zfsAutoSnap} weekly ${toString cfgSnapshots.weekly}";
|
||||||
|
};
|
||||||
|
restartIfChanged = false;
|
||||||
|
startAt = "weekly";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."zfs-snapshot-monthly" = {
|
||||||
|
description = "ZFS auto-snapshotting every month";
|
||||||
|
after = [ "zpool-import.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${zfsAutoSnap} monthly ${toString cfgSnapshots.monthly}";
|
||||||
|
};
|
||||||
|
restartIfChanged = false;
|
||||||
|
startAt = "monthly";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user