diff --git a/checks/backups/flake-module.nix b/checks/backups/flake-module.nix deleted file mode 100644 index 979317860..000000000 --- a/checks/backups/flake-module.nix +++ /dev/null @@ -1,203 +0,0 @@ -{ self, ... }: -{ - clan.machines.test-backup = { - imports = [ self.nixosModules.test-backup ]; - fileSystems."/".device = "/dev/null"; - boot.loader.grub.device = "/dev/null"; - }; - - clan.inventory.services = { - borgbackup.test-backup = { - roles.client.machines = [ "test-backup" ]; - roles.server.machines = [ "test-backup" ]; - }; - }; - flake.nixosModules = { - test-backup = - { - pkgs, - lib, - ... - }: - let - dependencies = [ - pkgs.stdenv.drvPath - ] - ++ builtins.map (i: i.outPath) (builtins.attrValues (builtins.removeAttrs self.inputs [ "self" ])); - closureInfo = pkgs.closureInfo { rootPaths = dependencies; }; - in - { - # Borgbackup overrides - services.borgbackup.repos.test-backups = { - path = "/var/lib/borgbackup/test-backups"; - authorizedKeys = [ (builtins.readFile ../assets/ssh/pubkey) ]; - }; - clan.borgbackup.destinations.test-backup.repo = lib.mkForce "borg@machine:."; - - clan.core.networking.targetHost = "machine"; - networking.hostName = "machine"; - - programs.ssh.knownHosts = { - machine.hostNames = [ "machine" ]; - machine.publicKey = builtins.readFile ../assets/ssh/pubkey; - }; - - services.openssh = { - enable = true; - settings.UsePAM = false; - settings.UseDns = false; - hostKeys = [ - { - path = "/root/.ssh/id_ed25519"; - type = "ed25519"; - } - ]; - }; - - users.users.root.openssh.authorizedKeys.keyFiles = [ ../assets/ssh/pubkey ]; - - # This is needed to unlock the user for sshd - # Because we use sshd without setuid binaries - users.users.borg.initialPassword = "hello"; - - systemd.tmpfiles.settings."vmsecrets" = { - "/root/.ssh/id_ed25519" = { - C.argument = "${../assets/ssh/privkey}"; - z = { - mode = "0400"; - user = "root"; - }; - }; - "/etc/secrets/ssh.id_ed25519" = { - C.argument = "${../assets/ssh/privkey}"; - z = { - mode = "0400"; - user = "root"; - }; - }; - "/etc/secrets/borgbackup/borgbackup.ssh" = { - C.argument = "${../assets/ssh/privkey}"; - z = { - mode = "0400"; - user = "root"; - }; - }; - "/etc/secrets/borgbackup/borgbackup.repokey" = { - C.argument = builtins.toString (pkgs.writeText "repokey" "repokey12345"); - z = { - mode = "0400"; - user = "root"; - }; - }; - }; - clan.core.facts.secretStore = "vm"; - clan.core.vars.settings.secretStore = "vm"; - - environment.systemPackages = [ self.packages.${pkgs.system}.clan-cli ]; - environment.etc.install-closure.source = "${closureInfo}/store-paths"; - nix.settings = { - substituters = lib.mkForce [ ]; - hashed-mirrors = null; - connect-timeout = lib.mkForce 3; - flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}''; - }; - system.extraDependencies = dependencies; - clan.core.state.test-backups.folders = [ "/var/test-backups" ]; - - clan.core.state.test-service = { - preBackupScript = '' - touch /var/test-service/pre-backup-command - ''; - preRestoreScript = '' - touch /var/test-service/pre-restore-command - ''; - postRestoreScript = '' - touch /var/test-service/post-restore-command - ''; - folders = [ "/var/test-service" ]; - }; - - fileSystems."/mnt/external-disk" = { - device = "/dev/vdb"; # created in tests with virtualisation.emptyDisks - autoFormat = true; - fsType = "ext4"; - options = [ - "defaults" - "noauto" - ]; - }; - - clan.localbackup.targets.hdd = { - directory = "/mnt/external-disk"; - preMountHook = '' - touch /run/mount-external-disk - ''; - postUnmountHook = '' - touch /run/unmount-external-disk - ''; - }; - }; - }; - perSystem = - { pkgs, ... }: - let - clanCore = self.checks.x86_64-linux.clan-core-for-checks; - in - { - checks = pkgs.lib.mkIf pkgs.stdenv.isLinux { - nixos-test-backups = self.clanLib.test.containerTest { - name = "nixos-test-backups"; - nodes.machine = { - imports = [ - self.nixosModules.clanCore - # Some custom overrides for the backup tests - self.nixosModules.test-backup - ] - ++ - # import the inventory generated nixosModules - self.clan.clanInternals.inventoryClass.machines.test-backup.machineImports; - clan.core.settings.directory = ./.; - }; - - testScript = '' - import json - start_all() - - # dummy data - machine.succeed("mkdir -p /var/test-backups /var/test-service") - machine.succeed("echo testing > /var/test-backups/somefile") - - # create - machine.succeed("clan backups create --debug --flake ${clanCore} test-backup") - machine.wait_until_succeeds("! systemctl is-active borgbackup-job-test-backup >&2") - machine.succeed("test -f /run/mount-external-disk") - machine.succeed("test -f /run/unmount-external-disk") - - # list - backup_id = json.loads(machine.succeed("borg-job-test-backup list --json"))["archives"][0]["archive"] - out = machine.succeed("clan backups list --debug --flake ${clanCore} test-backup").strip() - print(out) - assert backup_id in out, f"backup {backup_id} not found in {out}" - localbackup_id = "hdd::/mnt/external-disk/snapshot.0" - assert localbackup_id in out, "localbackup not found in {out}" - - ## borgbackup restore - machine.succeed("rm -f /var/test-backups/somefile") - machine.succeed(f"clan backups restore --debug --flake ${clanCore} test-backup borgbackup 'test-backup::borg@machine:.::{backup_id}' >&2") - assert machine.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed" - machine.succeed("test -f /var/test-service/pre-restore-command") - machine.succeed("test -f /var/test-service/post-restore-command") - machine.succeed("test -f /var/test-service/pre-backup-command") - - ## localbackup restore - machine.succeed("rm -rf /var/test-backups/somefile /var/test-service/ && mkdir -p /var/test-service") - machine.succeed(f"clan backups restore --debug --flake ${clanCore} test-backup localbackup '{localbackup_id}' >&2") - assert machine.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed" - machine.succeed("test -f /var/test-service/pre-restore-command") - machine.succeed("test -f /var/test-service/post-restore-command") - machine.succeed("test -f /var/test-service/pre-backup-command") - ''; - } { inherit pkgs self; }; - }; - }; -} diff --git a/checks/flake-module.nix b/checks/flake-module.nix index aa783d219..b5580ead2 100644 --- a/checks/flake-module.nix +++ b/checks/flake-module.nix @@ -33,7 +33,6 @@ in in getClanCoreTestModules ++ filter pathExists [ - ./backups/flake-module.nix ./devshell/flake-module.nix ./flash/flake-module.nix ./impure/flake-module.nix diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 869ed12d1..3f762b601 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -145,6 +145,7 @@ nav: - reference/clanModules/importer.md - reference/clanModules/iwd.md - reference/clanServices/localbackup.md + - reference/clanModules/localbackup.md - reference/clanModules/localsend.md - reference/clanModules/matrix-synapse.md - reference/clanModules/moonlight.md diff --git a/nixosModules/clanCore/postgresql/tests/flake-module.nix b/nixosModules/clanCore/postgresql/tests/flake-module.nix index 602aaa184..9a95c34c7 100644 --- a/nixosModules/clanCore/postgresql/tests/flake-module.nix +++ b/nixosModules/clanCore/postgresql/tests/flake-module.nix @@ -1,4 +1,4 @@ -{ self, ... }: +{ ... }: { perSystem = { ... }: @@ -22,28 +22,11 @@ roles.default.extraModules = [ { - imports = [ - # self.nixosModules.clanCore - self.clanServices.localbackup - ]; - clan.core.postgresql.enable = true; clan.core.postgresql.users.test = { }; clan.core.postgresql.databases.test.create.options.OWNER = "test"; - clan.core.postgresql.databases.test.restore.stopOnRestore = [ "sample-service" ]; - clan.localbackup.targets.hdd.directory = "/mnt/external-disk"; clan.core.settings.directory = ./.; - systemd.services.sample-service = { - wantedBy = [ "multi-user.target" ]; - script = '' - while true; do - echo "Hello, world!" - sleep 5 - done - ''; - }; - } ]; }; @@ -53,54 +36,15 @@ # TODO: Broken. Use instead of importer after fixing. # nodes.machine = { }; - testScript = + testScript = '' + start_all() + machine.wait_for_unit("postgresql") - { nodes, ... }: - - '' - start_all() - machine.wait_for_unit("postgresql") - machine.wait_for_unit("sample-service") - # Create a test table - machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -c 'CREATE TABLE test (id serial PRIMARY KEY);' test") - - machine.succeed("/run/current-system/sw/bin/localbackup-create >&2") - timestamp_before = int(machine.succeed("systemctl show --property=ExecMainStartTimestampMonotonic sample-service | cut -d= -f2").strip()) - - # import time - # time.sleep(5400000) - - machine.succeed("test -e /mnt/external-disk/snapshot.0/machine/var/backup/postgres/test/pg-dump || { echo 'pg-dump not found'; exit 1; }") - machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -d test -c 'INSERT INTO test DEFAULT VALUES;'") - machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -d test -c 'DROP TABLE test;'") - machine.succeed("test -e /var/backup/postgres/test/pg-dump || { echo 'pg-dump not found'; exit 1; }") - - machine.succeed("rm -rf /var/backup/postgres") - - machine.succeed("NAME=/mnt/external-disk/snapshot.0 FOLDERS=/var/backup/postgres/test /run/current-system/sw/bin/localbackup-restore >&2") - machine.succeed("test -e /var/backup/postgres/test/pg-dump || { echo 'pg-dump not found'; exit 1; }") - - machine.succeed(""" - set -x - ${nodes.machine.clan.core.state.test.postRestoreCommand} - """) - machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -l >&2") - machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -d test -c '\dt' >&2") - - timestamp_after = int(machine.succeed("systemctl show --property=ExecMainStartTimestampMonotonic sample-service | cut -d= -f2").strip()) - assert timestamp_before < timestamp_after, f"{timestamp_before} >= {timestamp_after}: expected sample-service to be restarted after restore" - - # Check that the table is still there - machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -d test -c 'SELECT * FROM test;'") - output = machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql --csv -c \"SELECT datdba::regrole FROM pg_database WHERE datname = 'test'\"") - owner = output.split("\n")[1] - assert owner == "test", f"Expected database owner to be 'test', got '{owner}'" - - # check if restore works if the database does not exist - machine.succeed("runuser -u postgres -- dropdb test") - machine.succeed("${nodes.machine.clan.core.state.test.postRestoreCommand}") - machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -d test -c '\dt' >&2") - ''; + # Create a test table + machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -c 'CREATE TABLE test (id serial PRIMARY KEY);' test") + machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -d test -c 'INSERT INTO test DEFAULT VALUES;'") + machine.succeed("runuser -u postgres -- /run/current-system/sw/bin/psql -d test -c 'SELECT * FROM test;'") + ''; }; }; }