diff --git a/nixos/modules/services/backup/restic.nix b/nixos/modules/services/backup/restic.nix
index 2388f1d6ca1..c38fd361d35 100644
--- a/nixos/modules/services/backup/restic.nix
+++ b/nixos/modules/services/backup/restic.nix
@@ -31,6 +31,59 @@ in
'';
};
+ rcloneOptions = mkOption {
+ type = with types; nullOr (attrsOf (oneOf [ str bool ]));
+ default = null;
+ description = ''
+ Options to pass to rclone to control its behavior.
+ See for
+ available options. When specifying option names, strip the
+ leading --. To set a flag such as
+ --drive-use-trash, which does not take a value,
+ set the value to the Boolean true.
+ '';
+ example = {
+ bwlimit = "10M";
+ drive-use-trash = "true";
+ };
+ };
+
+ rcloneConfig = mkOption {
+ type = with types; nullOr (attrsOf (oneOf [ str bool ]));
+ default = null;
+ description = ''
+ Configuration for the rclone remote being used for backup.
+ See the remote's specific options under rclone's docs at
+ . When specifying
+ option names, use the "config" name specified in the docs.
+ For example, to set --b2-hard-delete for a B2
+ remote, use hard_delete = true in the
+ attribute set.
+ Warning: Secrets set in here will be world-readable in the Nix
+ store! Consider using the rcloneConfigFile
+ option instead to specify secret values separately. Note that
+ options set here will override those set in the config file.
+ '';
+ example = {
+ type = "b2";
+ account = "xxx";
+ key = "xxx";
+ hard_delete = true;
+ };
+ };
+
+ rcloneConfigFile = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ description = ''
+ Path to the file containing rclone configuration. This file
+ must contain configuration for the remote specified in this backup
+ set and also must be readable by root. Options set in
+ rcloneConfig will override those set in this
+ file.
+ '';
+ };
+
repository = mkOption {
type = types.str;
description = ''
@@ -170,11 +223,22 @@ in
( resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts) )
( resticCmd + " check" )
];
+ # Helper functions for rclone remotes
+ rcloneRemoteName = builtins.elemAt (splitString ":" backup.repository) 1;
+ rcloneAttrToOpt = v: "RCLONE_" + toUpper (builtins.replaceStrings [ "-" ] [ "_" ] v);
+ rcloneAttrToConf = v: "RCLONE_CONFIG_" + toUpper (rcloneRemoteName + "_" + v);
+ toRcloneVal = v: if lib.isBool v then lib.boolToString v else v;
in nameValuePair "restic-backups-${name}" ({
environment = {
RESTIC_PASSWORD_FILE = backup.passwordFile;
RESTIC_REPOSITORY = backup.repository;
- };
+ } // optionalAttrs (backup.rcloneOptions != null) (mapAttrs' (name: value:
+ nameValuePair (rcloneAttrToOpt name) (toRcloneVal value)
+ ) backup.rcloneOptions) // optionalAttrs (backup.rcloneConfigFile != null) {
+ RCLONE_CONFIG = backup.rcloneConfigFile;
+ } // optionalAttrs (backup.rcloneConfig != null) (mapAttrs' (name: value:
+ nameValuePair (rcloneAttrToConf name) (toRcloneVal value)
+ ) backup.rcloneConfig);
path = [ pkgs.openssh ];
restartIfChanged = false;
serviceConfig = {