From f8ca64ee28f67286ebd23f876fee620a83f71ae3 Mon Sep 17 00:00:00 2001 From: Felix Albrigtsen Date: Mon, 26 Jan 2026 00:15:44 +0100 Subject: [PATCH] WIP: leonard: add backup.nix, mysqlBackup --- .sops.yaml | 9 ++++ hosts/leonard/backup.nix | 43 ++++++++++++++++++ hosts/leonard/configuration.nix | 1 + hosts/leonard/services/mysql.nix | 5 ++- .../services/www-kinealbrigtsen-no.nix | 3 ++ secrets/leonard/leonard.yaml | 45 +++++++++++++++++++ 6 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 hosts/leonard/backup.nix create mode 100644 secrets/leonard/leonard.yaml diff --git a/.sops.yaml b/.sops.yaml index 35f98bf..2d6dad6 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -3,6 +3,7 @@ keys: - &host_burnham age12cgkgx8xac77q0rwakp6zrfrzp45mhk7wj6t3y8s0xurt3k879usnm66ct - &host_challenger age1j43eqpnq5hy6zt3gmdtzdnne2yfvccd832kpt69qavst44leec6sj2l773 - &host_defiant age128md9emufxu35kgww3a90sw40vvc60f5xul9n9ndvw4lfnj3ndaqq44u64 + - &host_leonard age1djj3jvt0usurh43t8jsrs74t5pvj54w77vy7qgln9ykckag233eqyth4fl - &host_morn age14ar8q5454khxxf5ur2nxwk533nzycz2lh3635qwz35wh8yq0jpqskj2ksx - &user_felixalb_sisko age1phc4fkt25n4wtzg88sg3fhvmy6tv8pguyxp5c9js83ae3z374adsxfpqkl - &user_felixalb_worf age1nj7ju6f3jfvzw4c0sxywthjmztwp7rwqceun8xw2tlfrt7qymatser4vqf @@ -41,6 +42,14 @@ creation_rules: - *user_felixalb_sisko - *user_felixalb_worf + - path_regex: secrets/leonard/[^/]+\.yaml$ + key_groups: + - age: + - *host_leonard + - *bw_recovery + - *user_felixalb_sisko + - *user_felixalb_worf + - path_regex: secrets/morn/[^/]+\.yaml$ key_groups: - age: diff --git a/hosts/leonard/backup.nix b/hosts/leonard/backup.nix new file mode 100644 index 0000000..d2ead44 --- /dev/null +++ b/hosts/leonard/backup.nix @@ -0,0 +1,43 @@ +{ config, pkgs, lib, ... }: +{ + services.restic.backups = let + localJob = name: paths: { + inherit paths; + repository = "/mnt/feal-syn1/backup/leonard/${name}"; # TODO - Mount first + passwordFile = config.sops.secrets."restic/${name}".path; + initialize = true; + pruneOpts = [ + "--keep-daily 3" + "--keep-weekly 4" + "--keep-monthly 3" + ]; + }; + cloudJob = name: paths: { + inherit paths; + # "rsyncnet" connection details specified in /root/.ssh/config + extraOptions = [ "rclone.program=\"ssh rsyncnet\"" ]; + # repository = "rclone::/${name}"; + repository = "rclone:"; + passwordFile = config.sops.secrets."restic/${name}".path; + initialize = true; + pruneOpts = [ + # rsync.net keeps daily snapshots + "--keep-weekly 4" + "--keep-monthly 36" + ]; + }; + in { + # TODO - local NAS backups + mysql-remote = (cloudJob "postgres" [ "/var/backup/mysql" ]) // { + timerConfig.OnCalendar = "01:30"; # 1h after mysqlBackup + }; + # WIP + # postgres-remote = (cloudJob "postgres" [ "/tank/backup/postgresql" ]) // { + # timerConfig.OnCalendar = "05:15"; # 2h after postgresqlBackup + # }; + + }; + + sops.secrets."restic/mysql" = { }; + sops.secrets."restic/postgres" = { }; +} diff --git a/hosts/leonard/configuration.nix b/hosts/leonard/configuration.nix index cd098f5..ff7b9c8 100644 --- a/hosts/leonard/configuration.nix +++ b/hosts/leonard/configuration.nix @@ -8,6 +8,7 @@ ../../common/auto-upgrade.nix ./hardware-configuration.nix + ./backup.nix ./services/mysql.nix ./services/nginx.nix ./services/postgresql.nix diff --git a/hosts/leonard/services/mysql.nix b/hosts/leonard/services/mysql.nix index 128f2d6..a7212f7 100644 --- a/hosts/leonard/services/mysql.nix +++ b/hosts/leonard/services/mysql.nix @@ -6,5 +6,8 @@ package = pkgs.mariadb; }; - # TODO: services.mysqlBackup + services.mysqlBackup = { + enable = true; + calendar = "00:30:00"; + }; } diff --git a/hosts/leonard/services/www-kinealbrigtsen-no.nix b/hosts/leonard/services/www-kinealbrigtsen-no.nix index f970fd4..a0ccc66 100644 --- a/hosts/leonard/services/www-kinealbrigtsen-no.nix +++ b/hosts/leonard/services/www-kinealbrigtsen-no.nix @@ -20,6 +20,9 @@ }; } ]; + services.mysqlBackup.databases = [ + "www_kinealbrigtsen_no" + ]; services.phpfpm.pools.www-kinealbrigtsen-no = { user = "www-kinealbrigtsen-no"; diff --git a/secrets/leonard/leonard.yaml b/secrets/leonard/leonard.yaml new file mode 100644 index 0000000..ff3ceb9 --- /dev/null +++ b/secrets/leonard/leonard.yaml @@ -0,0 +1,45 @@ +restic: + mysql: ENC[AES256_GCM,data:eu666roPHKu5vH/LbxW9MToINgr+ilcdW0ttOZ4zul0=,iv:SpZ6TI8mwC78rVxmPcEyp7m63RsDyUCPVM5ydzR7Aoo=,tag:vjFsoTwwiaXTSIZ9nm4tTA==,type:str] + postgres: ENC[AES256_GCM,data:x8Z8avO2EsT/1AOPHeMX2Js9/PFlfKODSpa3DUp34OE=,iv:WLhkIwRkKlp/YMN7V6xX00+7n34pq45dGnvyvzkR2rk=,tag:jJU48KU11KbNm1ejMiLb6g==,type:str] +sops: + age: + - recipient: age1djj3jvt0usurh43t8jsrs74t5pvj54w77vy7qgln9ykckag233eqyth4fl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSM1owTEVLeEhobDEzQll5 + ejVyb3UzS0F0eDF3RnFMNWRhT2RXTTNLNjBrCnROUHE2REFGOGY4TFhVOE5lYlZB + UXN2Qk4vTDl0b0RRNmNLRVNkeGpqQ00KLS0tIGFlQkNqMlFmSDZ6Qk1QSHRnR2JO + L29iaDdTWFJ0L3REbDhvNEVIeGlQVE0KnsKH6C7mWlHb81aY+U9RUE3qEV9qeaWw + yCip5jRKD4gFgtMNLYTp3UsUPTojRGUuWEyHTLdXyDzQodtxi2rvmA== + -----END AGE ENCRYPTED FILE----- + - recipient: age146z3h3flw7spy5thznak8k5jh6yd68k9qrrehg8sdcwmyjv3vd7qvahdur + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0S25TZVY3MDlQNWN5ODEz + SHIrUXhZMTQvSW1nenhnMEpsMStySkxYVGxJCnE0bW90a202aUZ2eDl2YVA1dXc2 + RjlMSGVlSVlHSVNYOS9UY3JkczFQNlUKLS0tIGRzc1ZLZ0lzYm5iRzlSWG8zT0Rl + ckJzRXh3ZFdYS0FCTTQwUnBzRlB2S3MKRRfqGAYC+VGesmgV7BcJ57UHayzQRmsB + SPI9k3QheBFgjI/Oo//kctiZvphtyDopGdJfV2EFX+yFJk1vC0vwQA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1phc4fkt25n4wtzg88sg3fhvmy6tv8pguyxp5c9js83ae3z374adsxfpqkl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKUnJJUmMxQVBzdTRaZjAv + NmFxUzFLUFRzNnRpUzhtVUhGcUh2anQxYzB3CjRLeFFnQ1NKc1c0MmVsenFXSDR0 + SlVwZGFwRFQxSDVYL2NPSXdrVWRYY1UKLS0tIG5uemNXUkJyNExrMkNKQU84MWdP + NGN0c2lKTGJQa2tMamRWTUMwdVBWb1UKNxKhDvi0mbzF0eX5V/e3SDMCNEjb81z4 + z0y1R/rwlym7YDP00S0j2/PSQuYX7zRFFqikiYle2rR+CNG4LtU2jQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1nj7ju6f3jfvzw4c0sxywthjmztwp7rwqceun8xw2tlfrt7qymatser4vqf + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMNHBNRm80ZjhTWUlRZEJQ + MEdPbjZ2SGp3T0NQdmRiVmxSN3NNR3Fmd0I0Ckk5UXpYYmtSNThua2thV1ZrS0FF + R2MvMWNvYmFGZlM3ZTVwY1RkUXNPYXcKLS0tIEVJNElhUG5tTzlZaVpNQVc5dWsv + YkdCRlZncE8yYUVGYzVzSjNEeUU5VzAKGE1gMpKpt+O1+zx6s5nyfIbh1sYDnQxB + ksYLDyLXPyjcn5aFpbQ5MLoUQN1rvZK0TB3b2OTL8AJ8vThtx9SKwA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-01-25T22:56:53Z" + mac: ENC[AES256_GCM,data:U0ClvqjPYyO83Zq/IMwzfDmZME5ZPqqAIVRaBc0lAFszTV3Ga+Gx9fIuVjECkFKFuxz0pIOsYgJMl8IFlDi7XfH6BArbP7lTc99kW0/3EV9AnwvYIqFgX3jEaE2l7fRsStB+LD/Km93tppC0M6xqSCHxa/UXtR54e/cxwm+1PgY=,iv:llhk1vwjDuqr0io5edjxWy3fBu03XYEhoUaUeErBvys=,tag:BSJ/Yy1bhE1iJhTiMEfzOA==,type:str] + unencrypted_suffix: _unencrypted + version: 3.11.0