{ config, pkgs, lib, ... }: with lib; let zfssnap = pkgs.stdenv.mkDerivation rec { name = "zfssnap"; src = ./zfssnap.py; phases = [ "buildPhase" "checkPhase" "installPhase" ]; buildInputs = with pkgs; [makeWrapper]; python = pkgs.python39.withPackages (ps: with ps; [pyxdg pytimeparse dateutil]); buildPhase = '' substitute $src zfssnap \ --subst-var-by python ${escapeShellArg python} ''; doCheck = true; checkPhase = '' ${python}/bin/python -m py_compile zfssnap ''; installPhase = '' install -m 0755 -D -t $out/bin \ zfssnap wrapProgram $out/bin/zfssnap \ --prefix PATH : ${makeBinPath [config.boot.zfs.package]} ''; }; cfg = config.services.zfssnap; in { options = { services.zfssnap = { enable = mkEnableOption "zfssnap service"; config = mkOption { type = with types; attrsOf (attrsOf str); default = { keep = { within = "5m"; "5m" = "24"; hourly = "24"; daily = "31"; monthly = "-1"; }; }; }; snapInterval = mkOption { type = types.str; default = "*-*-* *:00/5:00 Europe/Berlin"; }; }; }; config = mkIf cfg.enable { systemd.services."zfssnap" = { description = "Create automatic ZFS snapshots"; after = [ "zfs-import.target" ]; wants = [ "zfssnap-prune.service" ]; before = [ "zfssnap-prune.service" ]; serviceConfig = { Type = "oneshot"; ExecStart = "${zfssnap}/bin/zfssnap -v"; }; }; systemd.services."zfssnap-prune" = { description = "Prune automatic ZFS snapshots"; after = [ "zfs-import.target" "zfssnap.service" ]; serviceConfig = { Type = "oneshot"; ExecStart = let mkSectionName = name: strings.escape [ "[" "]" ] (strings.toUpper name); zfssnapConfig = generators.toINI { inherit mkSectionName; } cfg.config; in "${zfssnap}/bin/zfssnap -v prune --config=${pkgs.writeText "zfssnap.ini" zfssnapConfig}"; }; }; systemd.timers."zfssnap" = { wantedBy = ["timers.target"]; timerConfig = { OnCalendar = cfg.snapInterval; Persistent = true; }; }; environment.systemPackages = [zfssnap]; }; }