From 22a01e0c0417b33ca2e5343645adede05a84ca7c Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Mon, 17 Aug 2026 20:47:36 +0300 Subject: [PATCH] test borg backup configuration --- nix/checks/module-eval.nix | 87 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/nix/checks/module-eval.nix b/nix/checks/module-eval.nix index 1de9137..f9f2a97 100644 --- a/nix/checks/module-eval.nix +++ b/nix/checks/module-eval.nix @@ -19,6 +19,10 @@ let services.rabbi-gerzi = { enable = true; + secretFiles = { + borgPassphrase = "/run/secrets/borg-passphrase"; + borgPrivateKey = "/run/secrets/borg-private-key"; + }; frontend.hostName = "www.example.test"; backend = { hostName = "api.example.test"; @@ -35,6 +39,14 @@ let phpOptions = evaluatedConfig.services.phpfpm.pools.rabbi-gerzi.phpOptions; + backupConfig = evaluatedConfig.services.borgbackup.jobs.rabbi-gerzi; + + backupService = evaluatedConfig.systemd.services.borgbackup-job-rabbi-gerzi; + + phpFpmService = evaluatedConfig.systemd.services.phpfpm-rabbi-gerzi; + + stateDir = evaluatedConfig.services.rabbi-gerzi.stateDir; + expectedUploadMaxFilesize = "upload_max_filesize = ${uploadLimits.phpUploadLimit}"; expectedPostMaxSize = "post_max_size = ${uploadLimits.phpUploadLimit}"; @@ -54,6 +66,81 @@ let passed = lib.hasInfix expectedNginxClientMaxBodySize backendVirtualHost.extraConfig; message = "nginx client_max_body_size is not 6m"; } + { + passed = backupConfig.repo == "ssh://mgjjruz9@mgjjruz9.repo.borgbase.com/./repo"; + message = "Borg repository is not the Rabbi Gerzi repository"; + } + { + passed = builtins.elem stateDir backupConfig.paths; + message = "Borg backup does not include the application state"; + } + { + passed = builtins.elem "/var/backup/rabbi-gerzi/rabbi-gerzi.dump" backupConfig.paths; + message = "Borg backup does not include the database dump"; + } + { + passed = backupConfig.startAt == "*-*-* 05:15:00"; + message = "Borg backup does not run at 05:15"; + } + { + passed = backupConfig.persistentTimer; + message = "Borg timer is not persistent"; + } + { + passed = + backupConfig.prune.keep.daily == 7 + && backupConfig.prune.keep.weekly == 4 + && backupConfig.prune.keep.monthly == 6; + message = "Borg retention policy is incorrect"; + } + { + passed = backupConfig.encryption.mode == "repokey-blake2"; + message = "Borg encryption mode is incorrect"; + } + { + passed = lib.hasInfix "/run/secrets/borg-passphrase" (backupConfig.encryption.passCommand); + message = "Borg passphrase secret is not wired"; + } + { + passed = lib.hasInfix "/run/secrets/borg-private-key" (backupConfig.environment.BORG_RSH); + message = "Borg SSH private key is not wired"; + } + { + passed = backupConfig.compression == "auto,zstd"; + message = "Borg compression is incorrect"; + } + { + passed = backupConfig.doInit; + message = "Borg repository initialization is disabled"; + } + { + passed = builtins.elem "/var/backup/rabbi-gerzi" backupConfig.readWritePaths; + message = "Borg job cannot write the database dump"; + } + { + passed = lib.hasInfix "phpfpm-rabbi-gerzi.service" (backupConfig.preHook); + message = "Borg pre-hook does not stop PHP-FPM"; + } + { + passed = lib.hasInfix "--format=custom" backupConfig.preHook; + message = "Borg pre-hook does not create a custom database dump"; + } + { + passed = lib.hasInfix "phpfpm-rabbi-gerzi.service" (backupConfig.postHook); + message = "Borg post-hook does not restore PHP-FPM"; + } + { + passed = phpFpmService.serviceConfig.KillSignal == "SIGQUIT"; + message = "PHP-FPM does not drain requests before stopping"; + } + { + passed = builtins.elem "sops-install-secrets.service" (backupService.after); + message = "Borg job is not ordered after secrets"; + } + { + passed = builtins.elem "postgresql.service" backupService.after; + message = "Borg job is not ordered after PostgreSQL"; + } ]; failedAssertions = lib.filter (assertion: !assertion.passed) assertions;