From 751d82f7e3099aa264c7c7df14aa32ab3a70d168 Mon Sep 17 00:00:00 2001 From: teutat3s Date: Wed, 28 Aug 2024 16:53:06 +0200 Subject: [PATCH 1/4] backups: rename pub-solar-os.backups.backups -> pub-solar-os.backups.restic --- modules/backups/default.nix | 10 +++++----- modules/keycloak/default.nix | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/backups/default.nix b/modules/backups/default.nix index 379309a..54c0bf0 100644 --- a/modules/backups/default.nix +++ b/modules/backups/default.nix @@ -61,7 +61,7 @@ in }; }; - backups = mkOption { + restic = mkOption { description = '' Periodic backups to create with Restic. ''; @@ -174,7 +174,7 @@ in runCheck = mkOption { type = types.bool; - default = (builtins.length config.pub-solar-os.backups.backups.${name}.checkOpts > 0); + default = (builtins.length config.pub-solar-os.backups.restic.${name}.checkOpts > 0); defaultText = literalExpression ''builtins.length config.services.backups.${name}.checkOpts > 0''; description = "Whether to run the `check` command with the provided `checkOpts` options."; example = true; @@ -256,16 +256,16 @@ in services.restic.backups = let repos = config.pub-solar-os.backups.repos; - backups = config.pub-solar-os.backups.backups; + restic = config.pub-solar-os.backups.restic; storeNames = builtins.attrNames repos; - backupNames = builtins.attrNames backups; + backupNames = builtins.attrNames restic; createBackups = backupName: map (storeName: { name = "${backupName}-${storeName}"; - value = repos."${storeName}" // backups."${backupName}"; + value = repos."${storeName}" // restic."${backupName}"; }) storeNames; in diff --git a/modules/keycloak/default.nix b/modules/keycloak/default.nix index 59d924b..38da6cf 100644 --- a/modules/keycloak/default.nix +++ b/modules/keycloak/default.nix @@ -58,7 +58,7 @@ }; }; - pub-solar-os.backups.backups.keycloak = { + pub-solar-os.backups.restic.keycloak = { paths = [ "/tmp/keycloak-backup.sql" ]; timerConfig = { OnCalendar = "*-*-* 03:00:00 Etc/UTC"; -- 2.44.1 From 1d92ef53caf8b65cece4b9f22f52601f660d0912 Mon Sep 17 00:00:00 2001 From: teutat3s Date: Wed, 28 Aug 2024 16:58:35 +0200 Subject: [PATCH 2/4] backups: storeName -> repoName --- modules/backups/default.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/backups/default.nix b/modules/backups/default.nix index 54c0bf0..5c286ef 100644 --- a/modules/backups/default.nix +++ b/modules/backups/default.nix @@ -258,15 +258,15 @@ in repos = config.pub-solar-os.backups.repos; restic = config.pub-solar-os.backups.restic; - storeNames = builtins.attrNames repos; + repoNames = builtins.attrNames repos; backupNames = builtins.attrNames restic; createBackups = backupName: - map (storeName: { - name = "${backupName}-${storeName}"; - value = repos."${storeName}" // restic."${backupName}"; - }) storeNames; + map (repoName: { + name = "${backupName}-${repoName}"; + value = repos."${repoName}" // restic."${backupName}"; + }) repoNames; in builtins.listToAttrs (lib.lists.flatten (map createBackups backupNames)); -- 2.44.1 From c0a3d90d63bb5358f626223698ce4b21ee4a8696 Mon Sep 17 00:00:00 2001 From: teutat3s Date: Wed, 28 Aug 2024 16:59:06 +0200 Subject: [PATCH 3/4] backups: add environmentFile option --- modules/backups/default.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules/backups/default.nix b/modules/backups/default.nix index 5c286ef..04b8324 100644 --- a/modules/backups/default.nix +++ b/modules/backups/default.nix @@ -39,6 +39,15 @@ in example = "/etc/nixos/restic-password"; }; + environmentFile = mkOption { + type = with types; nullOr str; + default = null; + description = '' + Read repository secrets as environment variables from a file. + ''; + example = "/etc/nixos/restic-env"; + }; + repository = mkOption { type = with types; nullOr str; default = null; @@ -57,6 +66,7 @@ in remotebackup = { repository = "sftp:backup@host:/backups/home"; passwordFile = "/etc/nixos/secrets/restic-password"; + environmentFile = "/etc/nixos/secrets/restic-env"; }; }; }; -- 2.44.1 From 4626fd85c0b6d84f6c667095d3df8e3e0a7f87fe Mon Sep 17 00:00:00 2001 From: teutat3s Date: Wed, 28 Aug 2024 17:10:17 +0200 Subject: [PATCH 4/4] mediawiki: add backups to garage bucket + storagebox Restic backups to garage S3 bucket nachtigall-backups https://garagehq.deuxfleurs.fr/documentation/connect/backup/#restic --- hosts/nachtigall/backups.nix | 23 +++++++++- hosts/nachtigall/configuration.nix | 5 -- modules/mediawiki/default.nix | 23 ++++++++++ secrets/restic-repo-garage-nachtigall-env.age | Bin 0 -> 2582 bytes secrets/restic-repo-garage-nachtigall.age | 43 ++++++++++++++++++ secrets/secrets.nix | 2 + 6 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 secrets/restic-repo-garage-nachtigall-env.age create mode 100644 secrets/restic-repo-garage-nachtigall.age diff --git a/hosts/nachtigall/backups.nix b/hosts/nachtigall/backups.nix index c5bf79b..46757bc 100644 --- a/hosts/nachtigall/backups.nix +++ b/hosts/nachtigall/backups.nix @@ -1,4 +1,4 @@ -{ flake, ... }: +{ config, flake, ... }: { age.secrets."restic-repo-droppie" = { file = "${flake.self}/secrets/restic-repo-droppie.age"; @@ -10,4 +10,25 @@ mode = "400"; owner = "root"; }; + age.secrets.restic-repo-garage-nachtigall = { + file = "${flake.self}/secrets/restic-repo-garage-nachtigall.age"; + mode = "400"; + owner = "root"; + }; + age.secrets.restic-repo-garage-nachtigall-env = { + file = "${flake.self}/secrets/restic-repo-garage-nachtigall-env.age"; + mode = "400"; + owner = "root"; + }; + + pub-solar-os.backups.repos.storagebox = { + passwordFile = config.age.secrets."restic-repo-storagebox".path; + repository = "sftp:u377325@u377325.your-storagebox.de:/backups"; + }; + + pub-solar-os.backups.repos.garage = { + passwordFile = config.age.secrets."restic-repo-garage-nachtigall".path; + environmentFile = config.age.secrets."restic-repo-garage-nachtigall-env".path; + repository = "s3:https://buckets.pub.solar/nachtigall-backups"; + }; } diff --git a/hosts/nachtigall/configuration.nix b/hosts/nachtigall/configuration.nix index cdc8243..c226ed0 100644 --- a/hosts/nachtigall/configuration.nix +++ b/hosts/nachtigall/configuration.nix @@ -59,11 +59,6 @@ database-password-file = config.age.secrets.keycloak-database-password.path; }; - pub-solar-os.backups.repos.storagebox = { - passwordFile = config.age.secrets."restic-repo-storagebox".path; - repository = "sftp:u377325@u377325.your-storagebox.de:/backups"; - }; - systemd.services.postgresql = { after = [ "var-lib-postgresql.mount" ]; requisite = [ "var-lib-postgresql.mount" ]; diff --git a/modules/mediawiki/default.nix b/modules/mediawiki/default.nix index 4512b55..63367ab 100644 --- a/modules/mediawiki/default.nix +++ b/modules/mediawiki/default.nix @@ -232,4 +232,27 @@ in }; }; }; + + pub-solar-os.backups.restic.mediawiki = { + paths = [ + "/var/lib/mediawiki/images" + "/var/lib/mediawiki/uploads" + "/tmp/mediawiki-backup.sql" + ]; + timerConfig = { + OnCalendar = "*-*-* 00:30:00 Etc/UTC"; + }; + initialize = true; + backupPrepareCommand = '' + ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d mediawiki > /tmp/mediawiki-backup.sql + ''; + backupCleanupCommand = '' + rm /tmp/mediawiki-backup.sql + ''; + pruneOpts = [ + "--keep-daily 7" + "--keep-weekly 4" + "--keep-monthly 3" + ]; + }; } diff --git a/secrets/restic-repo-garage-nachtigall-env.age b/secrets/restic-repo-garage-nachtigall-env.age new file mode 100644 index 0000000000000000000000000000000000000000..fc0c27bf224954b5a815f520dc31661704ade5b0 GIT binary patch literal 2582 zcmZXV*~|0>8O5cgQgYE!uoo`Ki=u+V_hp+*5{i~&l1yf@O!iDtMKW0@$t06~5rryf zEm9E$6$PbO#n$Db2$fQ$F1;*56_?A3D59cJ3RSVb2w#!<7o2A~=Xbm~yb%_DJzd&U zS==n^80=x-#`~|DCb zNge0&3X*bcQP4+Qfz&t`u~b3MUy3CAog zg-sn!_<6NVMKed`06c6&z$;>~9@NW>#M*M*FmN@)U@6WDGc32HR2qxb?kqI3Y^6}x zTBbW$7q8AhF(EL4Gch16F>dG16Id~jIqD~eGnS-x0gbRzGSbw@)2eby&YD3QIw6bG zOb!-ZlT1+J3TK%FfWpwe6F3@Kmnds%3N%orYX9OLOn^iOe+T5-m}xiRvUBZdK18c)YOZi6UC}-u{?6~3um$I z_1k=O-5$mQ=nAq2^JH;RO9`wp=;DASs#qmIQH%x4qXJ%p89DFmAt44VZ)bex!HIVy z9U-A=oCdsexL3MK^SX1V4he>t1Pf`EuczB;gxRW-^DsU5Xub$^lGygGcI-C2W2dOU z%=e2P;E(+TaTphr417_18SPrRS-EaFq16ia&6DKvCCih1Ed8&KGmgq%0d3V6guLZ_Oek&D#BXwYwsY*hhq*UXdJ~}Go^<# zRL^zk;@zHA261T1b*2|Hi;upPth2+lCF8!wfojU--G=N2Uv&7QaUzUCl{~XAdBc;= z=A^88&IU1@he)_MgK6m2{l$%sF`v7lbcleZ;dfad)@24-nm_I6nm2${exGYI>-FA&=- zBSrII9at5H8!e`}IjV}V(h+H?9>62P>+7^3A}b)HF~+MbPdEQPj@+ik@k< zwm40-tD)U_MPy)Dpu7!cqo z5~Z-`2{!|ob4vzI3~!VO30o8yq@c78SzF&Jjaqt*bhj?KKrJL!uMV=UU%Z_XvT4CU z6uyDP0H)8?HJn*-Dh~eNWrH^4Iqaes$Yd>~9$NKJda_gKuiW(p=zGt7B>d<7zqsRfTtMwV{pv68eBr+LefeMCZomEq z@$>i(zH|G1PdxbGzpEEN`}EDb?%#g&N2}+)|J>bA-CRBK((j|U? ssh-ed25519 iDKjwg yk6WgkJbk16Yqc/aWojwDePfNZN3XgaiacpZqufw1hc +qx3x0zCUB6l7qPS9R9xGO41s6ESGsNd/ixglY4gYDtY +-> ssh-ed25519 uYcDNw nDZXlykiDEZIA+Srg6imZFRLAzhykR3PDVrfWb693Sg +MBJrrXbtLzBozetgfZaE52o1ixsrPK6Ojdp8sXhI3dc +-> ssh-rsa f5THog +WngnjCboeUafoR5NOg/+NFeW/ILxonIrcl7iUQLXoObcFWtmgzEebcogo3kqnkdk +cj7NnqQ/sFiHdPCBr+VyiWcP4BJHJeWF/w+Ht9SYP5+WlHUkC2IPxlcMzJFyy2ro +9PDq8FaPX5ZqarOfBW+U1pQsegxG9wkfoSzoF8NVL0jU5mwubPc+1s0ycbjMcGzP +CSCpWY0OqqRbCXj8gVBNOOoELVhgbNCO0oRWh6Iafqjrx/rO4MNAdZmUF9DiTZML +8QQjBFR7G8/+4ehGHn/9PF/0yVVsnPaJTEo3juS/By+NVcCihwP3b0SgQkjtp73+ +2QZL4XImwR0bBLDla86IjvZWH7GkLzR8iAw75FZ/FGIxZ/XgwRcUqtcI8m105KAD +iX1v7ai0LUYko4RPSqdDItEdGjK31Dl4bCdaLakO+aZdtc+60c7hx8uEoTp7JY9W +Qmyv4rt5bVUUAeH0IyR72vTDpTtXSkbp0vypk6Zq+yhYjbe0wmakAPCF4WbIV9gQ +YIoSyicQ3NYxfrQGcQvmct2dNXXZcCr8BW704/J5w7ngw44FiZDUIC2y562sHD84 +9rFO0obVGERJa55+MnZB4UYMqU3eWs+mkxHgWotx5yEtO0wMpTP9IFk92scJeV8h +bdr6fq1p6gtFlSNlA7P8A0go1SWs+qIoO/PEPyznoss +-> ssh-rsa kFDS0A +RM1VIV11yDWaG7KDnXbVt+Qo9kIC5kPO1JwpROuxbTH8tDGbu7bC2mJ6qsZo1R5x +ewtmDVwv+Gogs2drjQeQgdZH3qN0cMt34micbW2lvBW4NmvAGKEQ+dkkUgIWIhy9 +dNuFBCHAGqfw7FDqvX1Mm3e50CsbIVqpurBXe882seMjm/nSVzGgjOOQVaQKmNSg +04s0gsLzN1f98kQtKuNPlG8Fun9y1bKLzWpBT2iriQInkhcWSwYqg1M0yM7U01j3 +Kcxn4LJmgB9qNkloEKNpHCze5fgIGyOf+MsG4VN90CvwpNxy/EHrEyncXDxSxiCt +A81PVHCZfC7fQTR+hF2s1xGcW9mmtRpPPSEUrGY84cW2k8m4E5A9J7MJZ7FOKe6C +OY3LoU5KCV292ujHqYs1c7JSJRqVq4IMCupsNL6afzB/Fe+cV6GX7bXh1ZUl9HT7 +B6j1QH2xA9OGz+6VDrB+B6cdnxp02zRZpuS19uPTJqpIg4Sgc4vvw7YFQfz8AfUD +/SafkBpVKznEHl1/gO7bOMa1nTkNBicUp6d2Z/zNtJ75NJPb3qYc4aVsaEuyMPts +ieMR/iieeiDOMPhedtibfCWZ+0YrtyIrkkUsPK5yG76VbJgMjSRyEP+bXTedih/b +bTkE78BoV5DmNxGEAva2BJpMKtn3Or8dCgSudoSlI14 +-> piv-p256 vRzPNw Al8mhhyZ/0YFf7OSKeGm3LZhowpCdcITOhtjmky7Ygnq +CxFNUst8+6e6Cra/j7Pa2lZs3lHGLCOWRInb1VZTr2M +-> piv-p256 zqq/iw A+r/W9OhuPjuGXRuhp1vW45k/QzCFO6VLfp1W6l7RJVU +GxunFSBPJnzd5t5Ar42vr06tyJkJvZhljlGkHVZOFOQ +-> ssh-ed25519 YFSOsg e7udSQwtwKETHB0Re59fb1DdiBBPLDbV/JHmUUI4GSU +054wi1iKJm8lnWDjONCk+h2vea0setKqdCpXHuJaecI +-> ssh-ed25519 iHV63A S2sle86zYVPjtCozODRjqtTs6a5GksTpJHkmO/WYzHU +7h5kS8Hc3BiyhiWerEa9xPX6o+D/bxoJLK1fXFq1jWc +-> ssh-ed25519 BVsyTA 7meQJdKDB4JLKsYmBPgDBUnWhil1fKnoijm+uzHDemY +1bxklkYv5KYab9fXjMtz/w5QTUYMlZFTQG/khBftlWo +-> ssh-ed25519 +3V2lQ n1bF6+o/16zx7dEt/Um1gL30mARiuPaE6z3N+qjFZx4 +7ZjmhkuJDYXLcMoUEA0wosWcWZ1T1oR45kVhFyQwN1E +--- TbpcaLv/1jF23nynpaw1XjSKsO2t9hAxovPQHKhXAoQ +P‰^¢f«E~¢÷ß6ÿO[Ö-cf]–øÄ9eÓ6Ñû‘4Eÿl2=sÿßW‡…O¿QFCzcõbÖTšÎÉÿ;[a \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index ab52663..e49ec68 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -54,6 +54,8 @@ in "restic-repo-droppie.age".publicKeys = nachtigallKeys ++ adminKeys; "restic-repo-storagebox.age".publicKeys = nachtigallKeys ++ adminKeys; + "restic-repo-garage-nachtigall.age".publicKeys = nachtigallKeys ++ adminKeys; + "restic-repo-garage-nachtigall-env.age".publicKeys = nachtigallKeys ++ adminKeys; "drone-db-secrets.age".publicKeys = flora6Keys ++ adminKeys; "drone-secrets.age".publicKeys = flora6Keys ++ adminKeys; -- 2.44.1