summaryrefslogtreecommitdiff
path: root/modules/borgsnap/default.nix
blob: 0a674e64776a44808a017e6c3eb49b12e643b292 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
{ config, pkgs, lib, flakeInputs, hostName, ... }:

with lib;

let
  borgsnap = flakeInputs.mach-nix.lib.${config.nixpkgs.system}.buildPythonPackage rec {
    pname = "borgsnap";
    src = ./borgsnap;
    version = "0.0.0";
    ignoreDataOutdated = true;

    requirements = ''
      atomicwrites
      pyprctl
      python-unshare
      python-dateutil
    '';
    postInstall = ''
      wrapProgram $out/bin/borgsnap \
        --prefix PATH : ${makeBinPath (with pkgs; [config.boot.zfs.package util-linux borgbackup])}:${config.security.wrapperDir}
    '';

    providers.python-unshare = "nixpkgs";
    overridesPre = [
      (self: super: { python-unshare = super.python-unshare.overrideAttrs (oldAttrs: { name = "python-unshare-0.2.1"; version = "0.2.1"; }); })
    ];

    _.tomli.buildInputs.add = with pkgs."python3Packages"; [ flit-core ];
  };

  cfg = config.services.borgsnap;
in {
  options = {
    services.borgsnap = {
      enable = mkEnableOption "borgsnap service";

      target = mkOption {
        type = types.str;
      };

      archive-prefix = mkOption {
        type = types.str;
        default = "yggdrasil.${hostName}.";
      };

      extraConfig = mkOption {
        type = with types; attrsOf str;
        default = {
          halfweekly = "8";
          monthly = "-1";
        };
      };

      verbosity = mkOption {
        type = types.int;
        default = config.services.zfssnap.verbosity;
      };

      sshConfig = mkOption {
        type = with types; nullOr str;
        default = null;
      };

      keyfile = mkOption {
        type = with types; nullOr str;
        default = null;
      };

      extraCreateArgs = mkOption {
        type = with types; listOf str;
        default = [];
      };
      extraCheckArgs = mkOption {
        type = with types; listOf str;
        default = [];
      };

      unknownUnencryptedRepoAccessOk = mkOption {
        type = types.bool;
        default = false;
      };
      hostnameIsUnique = mkOption {
        type = types.bool;
        default = true;
      };
    };
  };

  config = mkIf cfg.enable {
    warnings = mkIf (!config.services.zfssnap.enable) [
      "borgsnap will do nothing if zfssnap is not enabled"
    ];

    services.zfssnap.config.exec = {
      check = "${borgsnap}/bin/borgsnap --verbosity=${toString cfg.verbosity} --target ${escapeShellArg cfg.target} --archive-prefix ${escapeShellArg cfg.archive-prefix} check --cache-file /run/zfssnap-prune/archives-cache.json ${escapeShellArgs cfg.extraCheckArgs}";
      cmd = "${borgsnap}/bin/borgsnap --verbosity=${toString cfg.verbosity} --target ${escapeShellArg cfg.target} --archive-prefix ${escapeShellArg cfg.archive-prefix} create ${escapeShellArgs cfg.extraCreateArgs}";
    } // cfg.extraConfig;

    systemd.services."zfssnap-prune" = {
      serviceConfig = {
        Environment = [
          "BORG_BASE_DIR=/var/lib/borg"
          "BORG_CONFIG_DIR=/var/lib/borg/config"
          "BORG_CACHE_DIR=/var/lib/borg/cache"
          "BORG_SECURITY_DIR=/var/lib/borg/security"
          "BORG_KEYS_DIR=/var/lib/borg/keys"
        ]
        ++ optional cfg.unknownUnencryptedRepoAccessOk "BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes"
        ++ optional cfg.hostnameIsUnique "BORG_HOSTNAME_IS_UNIQUE=yes"
        ++ optional (!(isNull cfg.sshConfig)) "BORG_RSH=\"${pkgs.openssh}/bin/ssh -F ${pkgs.writeText "config" cfg.sshConfig}\""
        ++ optional (!(isNull cfg.keyfile)) "BORG_KEY_FILE=${cfg.keyfile}";
        RuntimeDirectory = "zfssnap-prune";
      };
    };
  };
}