summaryrefslogtreecommitdiff
path: root/modules/borgcopy/default.nix
blob: 475edbd90344e92d4f5342cb3bef97829cc9d54b (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
117
118
119
{ config, pkgs, lib, utils, flakeInputs, ... }:

with lib;

let
  copyBorg =
    with pkgs.poetry2nix;
    mkPoetryApplication {
      projectDir = cleanPythonSources { src = ./.; };

      overrides = overrides.withDefaults (self: super: {
        pyprctl = super.pyprctl.overridePythonAttrs (oldAttrs: {
          buildInputs = (oldAttrs.buildInputs or []) ++ [super.setuptools];
        });
        inherit (pkgs.python3Packages) python-unshare;
      });

      postInstall = ''
        wrapProgram $out/bin/copy_borg \
          --prefix PATH : ${makeBinPath (with pkgs; [util-linux borgbackup])}:${config.security.wrapperDir}
      '';
    };

  copyService = name: opts: nameValuePair "copy-borg@${utils.escapeSystemdPath name}" {
    serviceConfig = {
      Type = "oneshot";
      ExecStart = "${copyBorg}/bin/copy_borg --verbosity ${toString opts.verbosity} ${utils.escapeSystemdExecArgs [opts.from opts.to]}";
      TimeoutStartSec = "8h";
      # User = "borg";
      # Group = "borg";
      # StateDirectory = "borg";
      RuntimeDirectory = "copy-borg";
      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 opts.unknownUnencryptedRepoAccessOk "BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes"
      ++ optional opts.hostnameIsUnique "BORG_HOSTNAME_IS_UNIQUE=yes"
      ++ optional (!(isNull opts.sshConfig)) "BORG_RSH=\"${pkgs.openssh}/bin/ssh -F ${pkgs.writeText "config" opts.sshConfig}\""
      ++ optional (!(isNull opts.keyfile)) "BORG_KEY_FILE=${opts.keyfile}";

      LogRateLimitIntervalSec = 0;
    };
  };
  copyTimer = name: opts: nameValuePair "copy-borg@${utils.escapeSystemdPath name}" (recursiveUpdate {
    wantedBy = [ "timers.target" ];

    timerConfig = {
      Unit = "copy-borg@${utils.escapeSystemdPath name}.service";
    };
  } opts.timerOptions);

  cfg = config.services.copyborg;
in {
  options = {
    services.copyborg = mkOption {
      type = types.attrsOf (types.submodule {
        options = {
          from = mkOption {
            type = types.str;
            description = "Copy from this repository";
          };
          to = mkOption {
            type = types.str;
            description = "Copy to this repository";
          };

          verbosity = mkOption {
            type = types.int;
            default = 3;
            description = "Set verbosity";
          };

          sshConfig = mkOption {
            type = with types; nullOr str;
            default = null;
            description = "SSH client configuration";
          };

          keyfile = mkOption {
            type = with types; nullOr str;
            default = null;
            description = "Keyfile to pass to borg";
          };

          unknownUnencryptedRepoAccessOk = mkOption {
            type = types.bool;
            default = false;
            description = "Set `BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK`?";
          };
          hostnameIsUnique = mkOption {
            type = types.bool;
            default = true;
            description = "Set `BORG_HOSTNAME_IS_UNIQUE`?";
          };

          timerOptions = mkOption {
            # type = types.submodule utils.systemdUtils.unitOptions.stage2TimerOptions;
            type = types.attrs;
            default = {
              wantedBy = ["timers.target"];
            };
            description = "Systemd timer options";
          };
        };
      });
      default = {};
      description = "Copy borg archives from one repository to another";
    };
  };

  config = {
    systemd.services = mapAttrs' copyService cfg;
    systemd.timers = mapAttrs' copyTimer cfg;
  };
}