{ 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; }; to = mkOption { type = types.str; }; verbosity = mkOption { type = types.int; default = 3; }; sshConfig = mkOption { type = with types; nullOr str; default = null; }; keyfile = mkOption { type = with types; nullOr str; default = null; }; unknownUnencryptedRepoAccessOk = mkOption { type = types.bool; default = false; }; hostnameIsUnique = mkOption { type = types.bool; default = true; }; timerOptions = mkOption { # type = types.submodule utils.systemdUtils.unitOptions.stage2TimerOptions; type = types.attrs; default = { wantedBy = ["timers.target"]; }; }; }; }); default = {}; }; }; config = { systemd.services = mapAttrs' copyService cfg; systemd.timers = mapAttrs' copyTimer cfg; }; }