duplicity: migrate secrets to sops
This commit is contained in:
parent
d2ea4c5ffe
commit
a313f61351
|
@ -58,6 +58,8 @@
|
|||
./nixpatches/04-dart-2.7.0.patch
|
||||
# TODO: remove after upstreamed: https://github.com/NixOS/nixpkgs/pull/176476
|
||||
./nixpatches/06-whalebird-4.6.0-aarch64.patch
|
||||
# TODO: upstream
|
||||
./nixpatches/07-duplicity-rich-url.patch
|
||||
];
|
||||
};
|
||||
nixosSystem = import (patchedPkgs + "/nixos/lib/eval-config.nix");
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
|
||||
{
|
||||
services.duplicity.enable = true;
|
||||
# TODO: can we put an arbitrary shell expression here, to `cat` the url at runtime?
|
||||
services.duplicity.targetUrl = secrets.duplicity.url;
|
||||
# format: PASSPHRASE=<cleartext>
|
||||
services.duplicity.targetUrl = ''"$DUPLICITY_URL"'';
|
||||
services.duplicity.escapeUrl = false;
|
||||
# format: PASSPHRASE=<cleartext> \n DUPLICITY_URL=b2://...
|
||||
# two sisters
|
||||
# TODO: s/duplicity_passphrase/duplicity_env/
|
||||
services.duplicity.secretFile = config.sops.secrets.duplicity_passphrase.path;
|
||||
# NB: manually trigger with `systemctl start duplicity`
|
||||
services.duplicity.frequency = "daily";
|
||||
|
|
43
nixpatches/07-duplicity-rich-url.patch
Normal file
43
nixpatches/07-duplicity-rich-url.patch
Normal file
|
@ -0,0 +1,43 @@
|
|||
diff --git a/nixos/modules/services/backup/duplicity.nix b/nixos/modules/services/backup/duplicity.nix
|
||||
index 6949fa8b995..33d772ffa37 100644
|
||||
--- a/nixos/modules/services/backup/duplicity.nix
|
||||
+++ b/nixos/modules/services/backup/duplicity.nix
|
||||
@@ -54,6 +54,17 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
+ escapeUrl = mkOption {
|
||||
+ type = types.bool;
|
||||
+ example = false;
|
||||
+ default = true;
|
||||
+ description = ''
|
||||
+ Whether to escape the targetUrl when passing it to Duplicity as a CLI
|
||||
+ argument. One might disable this in order to make use of shell
|
||||
+ expressions such as environment variables.
|
||||
+ '';
|
||||
+ };
|
||||
+
|
||||
secretFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
@@ -148,7 +159,7 @@ in
|
||||
|
||||
script =
|
||||
let
|
||||
- target = escapeShellArg cfg.targetUrl;
|
||||
+ target = if cfg.escapeUrl then (escapeShellArg cfg.targetUrl) else cfg.targetUrl;
|
||||
extra = escapeShellArgs ([ "--archive-dir" stateDirectory ] ++ cfg.extraFlags);
|
||||
dup = "${pkgs.duplicity}/bin/duplicity";
|
||||
in
|
||||
@@ -158,9 +169,8 @@ in
|
||||
${lib.optionalString (cfg.cleanup.maxAge != null) "${dup} remove-older-than ${lib.escapeShellArg cfg.cleanup.maxAge} ${target} --force ${extra}"}
|
||||
${lib.optionalString (cfg.cleanup.maxFull != null) "${dup} remove-all-but-n-full ${toString cfg.cleanup.maxFull} ${target} --force ${extra}"}
|
||||
${lib.optionalString (cfg.cleanup.maxIncr != null) "${dup} remove-all-inc-of-but-n-full ${toString cfg.cleanup.maxIncr} ${target} --force ${extra}"}
|
||||
- exec ${dup} ${if cfg.fullIfOlderThan == "always" then "full" else "incr"} ${lib.escapeShellArgs (
|
||||
- [ cfg.root cfg.targetUrl ]
|
||||
- ++ concatMap (p: [ "--include" p ]) cfg.include
|
||||
+ exec ${dup} ${if cfg.fullIfOlderThan == "always" then "full" else "incr"} ${lib.escapeShellArg cfg.root} ${target} ${lib.escapeShellArgs (
|
||||
+ concatMap (p: [ "--include" p ]) cfg.include
|
||||
++ concatMap (p: [ "--exclude" p ]) cfg.exclude
|
||||
++ (lib.optionals (cfg.fullIfOlderThan != "never" && cfg.fullIfOlderThan != "always") [ "--full-if-older-than" cfg.fullIfOlderThan ])
|
||||
)} ${extra}
|
|
@ -1,14 +1,6 @@
|
|||
{
|
||||
ddns-he.password = "<REPLACEME>";
|
||||
|
||||
# format: b2://$key_id:$app_key@$bucket
|
||||
# create key with: b2 create-key --bucket uninsane-host-duplicity uninsane-host-duplicity-safe listBuckets,listFiles,readBuckets,readFiles,writeFiles
|
||||
# ^ run this until you get a key with no forward slashes :upside_down:
|
||||
# web-created keys are allowed to delete files, which you probably don't want for an incremental backup program
|
||||
duplicity.url = "b2://<REPLACEME:KEY_ID>:<REPLACEME:APPKEY>:<REPLACEME:BUCKET>";
|
||||
# remote backups will be encrypted using this (gpg) passphrase
|
||||
# duplicity.passphrase = "<REPLACEME>";
|
||||
|
||||
# to generate:
|
||||
# wg genkey > wg0.private
|
||||
# wg pubkey < wg0.private > wg0.public
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
duplicity_passphrase: ENC[AES256_GCM,data:oh3iXKAnkVz0B25kHYTBz4FG+3OURLe4yMXQuZDpHEXCXavPgOg=,iv:jfwzog65SDZTjXmm2OUI9zGffOSdRJxwmtCbZReRXPU=,tag:Z0mGljg0n1mQX2WcybZvaw==,type:str]
|
||||
#ENC[AES256_GCM,data:jBCVxBRtHCzOKua2vVVJ92TiNNrT8kABylT0tEz7JNNN0tmqsBCJMfDH9rBAMFpyf/orKXQVxkWV80qWVxzUwNDexwixrd0rs32gOXK1tQ==,iv:8d9EzGTXVEfmd8Su571zBySo5iIaQ9pDMLmC1lrYe5o=,tag:GDOxbWxNjTZ1unqLws2Wng==,type:comment]
|
||||
#ENC[AES256_GCM,data:KeKi7dkXTNiUZHfV7FyxKMO3AgR8ePeOE0H1ynZmtMLNRm4uHUSB7pL57n1s,iv:PQhqt0TAWJq/GondbIGYyN5pvonQGPpfQ0h2GqXYX6w=,tag:AnixV9wm/Unx4yYf6G4ntg==,type:comment]
|
||||
#ENC[AES256_GCM,data:fLQIrV4bWsUdPXxEbkYaXDgxr4B0dBs0+KiQC//xno02+8tNTxg5p956WZAK/iHPt7wGtm2bW6ay2oe18sgW3pDGLI1JOrOU0pBBcJSXns+1yJtgQSN8N4e+iVSM+EulppFk/fpMD20S3ToJhx2RvWmCcqHqH9wPHfD67B/1/IGSRhStH7AqCnfeB5ncN6d86C8Z+Q==,iv:02xufkIcNyvrALuD8P5TWk6CXxsFNvjTCiRQgquALTM=,tag:sGz4kFiku+R1gGLMkG1+jQ==,type:comment]
|
||||
#ENC[AES256_GCM,data:mfjzNHS72mmkebXz8tqrBpiVbHLWG7RTFfPTsLphoc3E5jz/NOQLQ0q76pJLDXlZQ+BIc5TE2RqDH649opWAAiM/hd2QFr8=,iv:0bjh5bWwcYS2FLUr3O9Moh1YJW+Id1a2cEkkH98maMs=,tag:0r61r+/kpGHbK0ttVCPhow==,type:comment]
|
||||
#ENC[AES256_GCM,data:l5E8Ji9v6shdOjDsg+pvRmSgWz7Spbq1s4lO01WUSaGzmfJdr/nnVrIE6gQNImTKfW8McqY4ZHTFTUSZ5Fs8BkjpSQ+9N1OIJl7wmg6G168zSL2hgQtpM4DbECQNgfjCJxAG9TN/2wnQkhN0f5Lrqw==,iv:HyfnJKJQABwMj7X7fQxVcakBs1PBpWVWlr6PyVn1EvY=,tag:84aMXP8kCGVksYpw389klg==,type:comment]
|
||||
duplicity_passphrase: ENC[AES256_GCM,data:WAQE+xhfRg+4N9Q1P9U8Lt7sVwpcEZFPJzyHIA+FIcCcZZhv+QmvCT/eTRtAOIFvII5l9f0A4GRnSEagalyaZgTgq7t8qOhvvB+s8cIj7prM1psnKstpx3+BxsinGOsZcPqbBxph9gdGuIVP3qH7pYAT+6GMPLnxW21s0r26mZFZM8Mu15VGyuvTz2Pknw==,iv:hu+6w6TWQensA4y5wBz1vPgw8YlBk5TuxEm2rRjV6Ao=,tag:UJ2joJZNxr/+O5y0dx6q9g==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
|
@ -32,8 +37,8 @@ sops:
|
|||
U0ZlOUljcE9BL1lhcmIrVVl6eFdTUmMKBHmv96FmkL/oQw9//ATfem6HtORRjcce
|
||||
xJNwnsdrEqrBS3sG6xDkmJYOjaFrg1pwxYZRG87zeLShgkXkMNvz2A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-06-07T01:44:34Z"
|
||||
mac: ENC[AES256_GCM,data:Mf0unN7x/x+hI56ECMuyLpLWoxRg5APIyhB7UtY7BzQ/UzHEYE/mektw7LrvPm3GkhkSBeTa8yw9UUeMkNBgNFfp6df3oiIZnZc/RriXUWasgtqeMWD35LYQqz/jZ8O2usP5E5OySOuzV332ZHhrNqxUVABQdBY8Kz6anEFMlZU=,iv:IVQFzyOrDevcuMNr1ul/FtJnDLMw+FeeQy5nLWNb3Jc=,tag:fvmbjYszc4+Y6vV8wtJx0g==,type:str]
|
||||
lastmodified: "2022-06-07T09:30:04Z"
|
||||
mac: ENC[AES256_GCM,data:B/Tsq5YNrLd7MziJASlv0urTOJRKn8LHvRZFK/2qJBDrbHODQMVzQL35Yw4AtdQSDYcFm4RxQzqQ2mVRabb2Np0Duft8bH3v3EhknP2Jokx+lzmo878UFzumu2BP7lMnNeeYL6vIMVqPmhOl1RIwlvLvczKEpzW/hUHIvsWGsis=,iv:+eWHnG2ijszBiROJuEhbdEtc0Vy026Bmf1Tj45fBy7g=,tag:MCQAQm132fBH8kh/wpf9fQ==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.7.3
|
||||
|
|
Loading…
Reference in New Issue
Block a user