From f9b4b7133b7b46f83b6cfb03dea69f927e2c27ba Mon Sep 17 00:00:00 2001 From: Greg Hellings Date: Thu, 15 Aug 2024 04:48:29 +0000 Subject: [PATCH] Make backups more fun with syncthing --- hosts/linode/nextcloud.nix | 2 +- hosts/linode/postgres.nix | 4 +-- modules/nixos/backup.nix | 57 ++++++++++++++++++------------------ modules/nixos/default.nix | 1 + modules/nixos/syncthing.nix | 26 ++++++++++++++++ secrets/restic-env.age | 30 +++++++++++++++++++ secrets/restic-pw.age | Bin 0 -> 1611 bytes secrets/secrets.nix | 3 ++ 8 files changed, 92 insertions(+), 31 deletions(-) create mode 100644 modules/nixos/syncthing.nix create mode 100644 secrets/restic-env.age create mode 100644 secrets/restic-pw.age diff --git a/hosts/linode/nextcloud.nix b/hosts/linode/nextcloud.nix index 08239e6..ed61c7e 100644 --- a/hosts/linode/nextcloud.nix +++ b/hosts/linode/nextcloud.nix @@ -33,6 +33,6 @@ greg.backup.jobs.nextcloud-bkup = { src = "/var/lib/nextcloud"; dest = "nextcloud-backup"; - user = "nextcloud"; + id = "rbfco-rvmis"; }; } diff --git a/hosts/linode/postgres.nix b/hosts/linode/postgres.nix index edd035c..8172ddd 100644 --- a/hosts/linode/postgres.nix +++ b/hosts/linode/postgres.nix @@ -56,8 +56,8 @@ root root postgres }; greg.backup.jobs.greg-postgresql-backup = { - src = "/var/backup/postgresql"; + src = config.services.postgresqlBackup.location; dest = "linode-postgres"; - user = "postgres"; + id = "9pwvg-s257a"; }; } diff --git a/modules/nixos/backup.nix b/modules/nixos/backup.nix index 8ce05ac..bbfe8d8 100644 --- a/modules/nixos/backup.nix +++ b/modules/nixos/backup.nix @@ -3,18 +3,25 @@ let cfg = config.greg.backup; - makeTimer = name: job: { - timerConfig.OnCalendar = "daily"; - wantedBy = [ "timers.target" ]; + where = j: "${config.services.syncthing.dataDir}/${j.dest}"; + + makeSyncFolders = name: job: { + devices = [ "chronicles" ]; + enable = true; + id = job.id; + label = job.dest; + path = where job; + type = "sendonly"; }; - makeService = name: job: { - serviceConfig = { - User = job.user; - ExecStartPre = lib.optionalString (job.pre != "") job.pre; - ExecStart = "${pkgs.rsync}/bin/rsync -avz --delete -e '${pkgs.openssh}/bin/ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null' ${job.src}/ backup@chronicles.shire-zebra.ts.net:/volume1/NetBackup/${job.dest}"; - ExecStartPost = lib.optionalString (job.post != "") job.post; - }; + makeRestic = name: job: let + who = "${config.services.syncthing.user}:${config.services.syncthing.group}"; + in rec { + initialize = true; + passwordFile = config.age.secrets.restic-pw.path; + paths = [ job.src ]; + repository = where job; + backupCleanupCommand = ''${pkgs.coreutils}/bin/chown -R ${who} "${repository}"''; }; in with lib; { @@ -36,22 +43,9 @@ in with lib; { type = types.str; }; - user = mkOption { + id = mkOption { type = types.str; - default = "root"; - description = "User to run backup as"; - }; - - pre = mkOption { - type = types.str; - default = ""; - description = "Commands to run before backup"; - }; - - post = mkOption { - type = types.str; - default = ""; - description = "Commands to run after backup"; + description = "The unique folder ID for this"; }; }; } @@ -62,9 +56,16 @@ in with lib; { config = mkIf ( ( attrValues cfg.jobs ) != [] ) { - systemd = { - timers = mapAttrs makeTimer cfg.jobs; - services = mapAttrs makeService cfg.jobs; + age.secrets = { + restic-pw.file = ../../secrets/restic-pw.age; + restic-env.file = ../../secrets/restic-env.age; + }; + greg.syncthing = { + enable = true; + }; + services = { + syncthing.settings.folders = mapAttrs makeSyncFolders cfg.jobs; + restic.backups = mapAttrs makeRestic cfg.jobs; }; }; } diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index db22ec7..7e305f3 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -16,6 +16,7 @@ ./router.nix ./rpi4.nix ./sway.nix + ./syncthing.nix ./tailscale.nix ./vmdev.nix ]; diff --git a/modules/nixos/syncthing.nix b/modules/nixos/syncthing.nix new file mode 100644 index 0000000..7457bb7 --- /dev/null +++ b/modules/nixos/syncthing.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.greg.syncthing; +in with lib; { + options.greg.syncthing = { + enable = mkEnableOption "Setup my personal minimal configuration for Syncthing"; + }; + + config = mkIf cfg.enable { + services.syncthing = { + enable = true; + overrideFolders = true; + overrideDevices = true; + settings = { + devices = { + chronicles.id = "7FI6Y3M-C7YQEDI-IB345L6-RKLXMB6-AEIV57Y-3J2RCXQ-MK6QRNK-EINPXAE"; + linode.id = "IJMMXPR-WNALZBD-FMJH5W5-WV7XGJY-HLJTKGT-5TKHJIH-75LT56D-UUZCYQE"; + }; + options = { + urAccepted = -1; + }; + }; + }; + }; +} diff --git a/secrets/restic-env.age b/secrets/restic-env.age new file mode 100644 index 0000000..126530b --- /dev/null +++ b/secrets/restic-env.age @@ -0,0 +1,30 @@ +age-encryption.org/v1 +-> ssh-ed25519 oyEmTw +5GE8yJvBQ+4p4vAbN89YCHBjWgn2H/jWDAtIas5pig ++qMZZtLMhVwHpAaJ34lTDjJZi8etcnjebfnWHTcLjlk +-> ssh-ed25519 mOmPfg GjmciOCIpxZY2o0JmgojwolXZkA3DAnhNkKoPa+/6i0 +I6W8b+iu1IJIfM5eCUxuT+oHO6leCT2ck4+Ltb8fiPY +-> ssh-ed25519 YJiRbw hKbIcwyh/xp90tbvytCCZfmBwwt+28bY4DJlXvo6dA4 +KaQsKvPAmtZUvi2rxXwR2FcbIdo9SRr1lEyqsMp1G30 +-> ssh-ed25519 aY2AXA aXtJ66mKlSqxJxuQdVPiFSvPNpxfm7yseoMIuu6vYA4 +ZNQ/Zo92gat15/E49fFPNRKZI5jRxnD/zrRfUwNc8GI +-> ssh-ed25519 xNtnoA 5tK6SvHTxNka0CQDLDtukwKAs8mlrRAALK1AkAY+tyQ +eF0dQ3SFQKCD0FuVEXwE+CjOUm8vjQSIsCFviqI3pfk +-> ssh-ed25519 AQhf1g Iei85IkkHUExExezcFG21YG0yeMrI+SmlMmtLoHtT3I +ZsuWFBoi9DSSgwfIpJlyrXIbgXOH+0gm/yqJaIhga4o +-> ssh-ed25519 Nl/5yA NPp9yfa0MLHQ5+fkcNEtMvE5JyWG2F53rPZZs0IU6mo +BNSb4BvGkpEJSPMMRbSbqsXavQ1QcEr3bGEES5cr4hw +-> ssh-ed25519 GdLgCQ dYWQFiv4dLFM9D22OVcVcJYZwKXHza4EnaEZyp5ixno +bHN9mf7atf/gJRs+4FCiK30qBmBrORaYzbFDSfPTIpY +-> ssh-ed25519 tOH/HQ wny8+QHHl3nvsKu8VUrh+Eqr1BmFoxio5DkeVhganj8 +H4AFAM03fjbUAWin/rkKZm7nS91jzTRRR27A8LnK/J0 +-> ssh-ed25519 FpzvfQ WXL1WjxG505w21Hj8su1crkeOinTes71D/REK5NlTkA +rhDkdNUD453ZyEqTk202HgWCqK3OtHNRZ1xkH3NJfuo +-> ssh-ed25519 kdPvzQ pEA4KU23MwZC1xVILf2wL/OYfi56aqRL/KqPQBIHIEM +bOZZYz9H9LAJzvljPgk6tfY/HH0OXrWBbA/nSC2ae+c +-> ssh-ed25519 onmXpg q8ay0LwB9UON2j2owU2uZYl6lPAM1tF5FZvdW0Ne1Q4 +0O2R3tOYeCZqNBn1BaWMJbaCDo6KpTnzt8h56j7a3gw +-> ssh-ed25519 CnhD0g dYMvLeb4YTYQbm7eXPfI5J0OI7SISQvD0cVB5d5cSCw ++YlYOF9gUFycpy6PqJeE4qLUBP7PtWfMgRcjsVOSFGo +--- 8OYRi2tJeg668hNGOqqLOkyHPGmX8jdtQIPfQS8Tf3k +"sΠ.>'X1R4E]@C䀵8roJ񄱇_I| ̍t sOm!.ӏm|-$*c@#m +Rg7w\/8 \ No newline at end of file diff --git a/secrets/restic-pw.age b/secrets/restic-pw.age new file mode 100644 index 0000000000000000000000000000000000000000..6a2e62ed8f6f4e0bad091bc7d9696e13351519f2 GIT binary patch literal 1611 zcmZY9yX))-6$fxZuox?aTiD2eAVT<=$0Rd}EO$5W_xm{kg}f$@$z$@EOp-j5w%d8s|zk-Cy1R}3wA4FrT*&QtxoyjobNd&%Co1eO@{S0m0kP&ZpgtI-aWnE zk7Mzar3i+>#J*eE#(C^hacfMk(K8r<6CXN{@oHRk-wV&;WwxD=*z7I7t9P_9chsgZ z;3U?pm)ESn_Me<@@wl#+D4tOTk=wC^v1a4``pS@M`_sVuDSgR@^Z9- zC;h-g5O(pBqL&UO;?2-qF~^;oK^(m$Xgh+k25gQO-vNXbtGOmh&EsbiX>td>Q~YYa z)Xq|A#gDyuGwqm5JcIBcP%E9G_l901V>%Y?xX5E@Ds86~+P=N+ctiJcAgxmOn4NJd zw*Z5kX|*yp$I7O|c~CMW zn)&|V($_(u;Bm0u%8fLO3!Lu{owUw$oE8k}Q$gOzsXdH$qA(j&KYGoD#%~Wf^i@^J zcNq;6cq}2x1WX5-8`vZ|0e;dLjsUy2u_6M`0YZ7H(Z|b4YBh+hfv zBU|-WHKdDEY>YZN&D|rVg&9Wg;nw(WxEUw8%w@h897r-sxb5;4!YW3b{P@&EmFidZ zgorqYzts3t$!T*Rx=z|TmQC>~votUj9WHp@#3%Kdsfa|d>+#04p~I!Lxar3C_gpW|hrXVMErjVA|rYfHG> zHebv=D^rwAs<&i`13rc+9I31Jc{*Ul=3TXTnld91P8-Blh&dUI_cu*gkl3>`4| z0s<9DFAJIQR~5C`vL8q6d)woOlWkJkL`mxZ7h0RGzCk?hlE4Br>CdA7D^d|WT!Qs26}bpJA;@Y zc!&gUois)_rJ%>m8*Vd4b60-(nUjA0=KVLX|7Q|kkDd5ee|+<^Xv$yx=I7lve)+9` z|EP?#KgX}kzrF&#`{5_={PQ~>fAKHw-QWG;J@ND8_3!;3fB2uj{PZWw$3OhRN5B1w s^R=(O6Tbi1KV