diff --git a/.forgejo/workflows/check.yml b/.forgejo/workflows/check.yml index fe6890e..0ab1544 100644 --- a/.forgejo/workflows/check.yml +++ b/.forgejo/workflows/check.yml @@ -18,14 +18,20 @@ jobs: # Prevent cache garbage collection by creating GC roots mkdir -p /var/lib/gitea-runner/tankstelle/.local/state/nix/results - for target in $(nix flake show --json --all-systems | jq ' + for target in $(nix flake show --json --all-systems | jq --raw-output ' .["nixosConfigurations"] | to_entries[] | - .key - ' | tr -d '"' + .key' ); do nix --print-build-logs --verbose --accept-flake-config --access-tokens '' \ build --out-link /var/lib/gitea-runner/tankstelle/.local/state/nix/results/"$target" ".#nixosConfigurations.${target}.config.system.build.toplevel" done - nix --print-build-logs --verbose --accept-flake-config --access-tokens '' flake check + for check in $(nix flake show --json --all-systems | jq --raw-output ' + .checks."x86_64-linux" | + to_entries[] | + .key' + ); do + nix --print-build-logs --verbose --accept-flake-config --access-tokens '' \ + build --out-link /var/lib/gitea-runner/tankstelle/.local/state/nix/results/"$check" ".#checks.x86_64-linux.${check}" + done diff --git a/flake.nix b/flake.nix index 34aeb3b..40f049c 100644 --- a/flake.nix +++ b/flake.nix @@ -82,7 +82,7 @@ master = import inputs.master { inherit system; }; }; - packages = import ./tests ({ inherit inputs self; } // args); + checks = import ./tests ({ inherit inputs self; } // args); devShells.default = pkgs.mkShell { buildInputs = with pkgs; [ diff --git a/hosts/nachtigall/configuration.nix b/hosts/nachtigall/configuration.nix index bc7e76d..cdc8243 100644 --- a/hosts/nachtigall/configuration.nix +++ b/hosts/nachtigall/configuration.nix @@ -59,11 +59,16 @@ database-password-file = config.age.secrets.keycloak-database-password.path; }; - pub-solar-os.backups.stores.storagebox = { + 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" ]; + }; + # This value determines the NixOS release with which your system is to be # compatible, in order to avoid breaking some software such as database # servers. You should change this only after NixOS release notes say you diff --git a/modules/backups/default.nix b/modules/backups/default.nix index 996392c..379309a 100644 --- a/modules/backups/default.nix +++ b/modules/backups/default.nix @@ -13,257 +13,259 @@ let }; # Type for a valid systemd unit option. Needed for correctly passing "timerConfig" to "systemd.timers" inherit (utils.systemdUtils.unitOptions) unitOption; + inherit (lib) + literalExpression + mkOption + mkPackageOption + types + ; in { options.pub-solar-os.backups = { - stores = - with lib; - mkOption { - description = '' - Periodic backups to create with Restic. - ''; - type = types.attrsOf ( - types.submodule ( - { name, ... }: - { - options = { - passwordFile = mkOption { - type = types.str; - description = '' - Read the repository password from a file. - ''; - example = "/etc/nixos/restic-password"; - }; - - repository = mkOption { - type = with types; nullOr str; - default = null; - description = '' - repository to backup to. - ''; - example = "sftp:backup@192.168.1.100:/backups/${name}"; - }; + repos = mkOption { + description = '' + Configuration of Restic repositories. + ''; + type = types.attrsOf ( + types.submodule ( + { name, ... }: + { + options = { + passwordFile = mkOption { + type = types.str; + description = '' + Read the repository password from a file. + ''; + example = "/etc/nixos/restic-password"; }; - } - ) - ); - default = { }; - example = { - remotebackup = { - repository = "sftp:backup@host:/backups/home"; - passwordFile = "/etc/nixos/secrets/restic-password"; - }; - }; - }; - - backups = - with lib; - mkOption { - description = '' - Periodic backups to create with Restic. - ''; - type = types.attrsOf ( - types.submodule ( - { name, ... }: - { - options = { - paths = mkOption { - # This is nullable for legacy reasons only. We should consider making it a pure listOf - # after some time has passed since this comment was added. - type = types.nullOr (types.listOf types.str); - default = [ ]; - description = '' - Which paths to backup, in addition to ones specified via - `dynamicFilesFrom`. If null or an empty array and - `dynamicFilesFrom` is also null, no backup command will be run. - This can be used to create a prune-only job. - ''; - example = [ - "/var/lib/postgresql" - "/home/user/backup" - ]; - }; - - exclude = mkOption { - type = types.listOf types.str; - default = [ ]; - description = '' - Patterns to exclude when backing up. See - https://restic.readthedocs.io/en/latest/040_backup.html#excluding-files for - details on syntax. - ''; - example = [ - "/var/cache" - "/home/*/.cache" - ".git" - ]; - }; - - timerConfig = mkOption { - type = types.nullOr (types.attrsOf unitOption); - default = { - OnCalendar = "daily"; - Persistent = true; - }; - description = '' - When to run the backup. See {manpage}`systemd.timer(5)` for - details. If null no timer is created and the backup will only - run when explicitly started. - ''; - example = { - OnCalendar = "00:05"; - RandomizedDelaySec = "5h"; - Persistent = true; - }; - }; - - user = mkOption { - type = types.str; - default = "root"; - description = '' - As which user the backup should run. - ''; - example = "postgresql"; - }; - - extraBackupArgs = mkOption { - type = types.listOf types.str; - default = [ ]; - description = '' - Extra arguments passed to restic backup. - ''; - example = [ "--exclude-file=/etc/nixos/restic-ignore" ]; - }; - - extraOptions = mkOption { - type = types.listOf types.str; - default = [ ]; - description = '' - Extra extended options to be passed to the restic --option flag. - ''; - example = [ "sftp.command='ssh backup@192.168.1.100 -i /home/user/.ssh/id_rsa -s sftp'" ]; - }; - - initialize = mkOption { - type = types.bool; - default = false; - description = '' - Create the repository if it doesn't exist. - ''; - }; - - pruneOpts = mkOption { - type = types.listOf types.str; - default = [ ]; - description = '' - A list of options (--keep-\* et al.) for 'restic forget - --prune', to automatically prune old snapshots. The - 'forget' command is run *after* the 'backup' command, so - keep that in mind when constructing the --keep-\* options. - ''; - example = [ - "--keep-daily 7" - "--keep-weekly 5" - "--keep-monthly 12" - "--keep-yearly 75" - ]; - }; - - runCheck = mkOption { - type = types.bool; - default = (builtins.length config.pub-solar-os.backups.backups.${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; - }; - - checkOpts = mkOption { - type = types.listOf types.str; - default = [ ]; - description = '' - A list of options for 'restic check'. - ''; - example = [ "--with-cache" ]; - }; - - dynamicFilesFrom = mkOption { - type = with types; nullOr str; - default = null; - description = '' - A script that produces a list of files to back up. The - results of this command are given to the '--files-from' - option. The result is merged with paths specified via `paths`. - ''; - example = "find /home/matt/git -type d -name .git"; - }; - - backupPrepareCommand = mkOption { - type = with types; nullOr str; - default = null; - description = '' - A script that must run before starting the backup process. - ''; - }; - - backupCleanupCommand = mkOption { - type = with types; nullOr str; - default = null; - description = '' - A script that must run after finishing the backup process. - ''; - }; - - package = mkPackageOption pkgs "restic" { }; - - createWrapper = lib.mkOption { - type = lib.types.bool; - default = true; - description = '' - Whether to generate and add a script to the system path, that has the same environment variables set - as the systemd service. This can be used to e.g. mount snapshots or perform other opterations, without - having to manually specify most options. - ''; - }; + repository = mkOption { + type = with types; nullOr str; + default = null; + description = '' + repository to backup to. + ''; + example = "sftp:backup@192.168.1.100:/backups/${name}"; }; - } - ) - ); - default = { }; - example = { - localbackup = { - paths = [ "/home" ]; - exclude = [ "/home/*/.cache" ]; - initialize = true; - }; - remotebackup = { - paths = [ "/home" ]; - extraOptions = [ - "sftp.command='ssh backup@host -i /etc/nixos/secrets/backup-private-key -s sftp'" - ]; - timerConfig = { - OnCalendar = "00:05"; - RandomizedDelaySec = "5h"; }; + } + ) + ); + + default = { }; + example = { + remotebackup = { + repository = "sftp:backup@host:/backups/home"; + passwordFile = "/etc/nixos/secrets/restic-password"; + }; + }; + }; + + backups = mkOption { + description = '' + Periodic backups to create with Restic. + ''; + type = types.attrsOf ( + types.submodule ( + { name, ... }: + { + options = { + paths = mkOption { + # This is nullable for legacy reasons only. We should consider making it a pure listOf + # after some time has passed since this comment was added. + type = types.nullOr (types.listOf types.str); + default = [ ]; + description = '' + Which paths to backup, in addition to ones specified via + `dynamicFilesFrom`. If null or an empty array and + `dynamicFilesFrom` is also null, no backup command will be run. + This can be used to create a prune-only job. + ''; + example = [ + "/var/lib/postgresql" + "/home/user/backup" + ]; + }; + + exclude = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + Patterns to exclude when backing up. See + https://restic.readthedocs.io/en/latest/040_backup.html#excluding-files for + details on syntax. + ''; + example = [ + "/var/cache" + "/home/*/.cache" + ".git" + ]; + }; + + timerConfig = mkOption { + type = types.nullOr (types.attrsOf unitOption); + default = { + OnCalendar = "daily"; + Persistent = true; + }; + description = '' + When to run the backup. See {manpage}`systemd.timer(5)` for + details. If null no timer is created and the backup will only + run when explicitly started. + ''; + example = { + OnCalendar = "00:05"; + RandomizedDelaySec = "5h"; + Persistent = true; + }; + }; + + user = mkOption { + type = types.str; + default = "root"; + description = '' + As which user the backup should run. + ''; + example = "postgresql"; + }; + + extraBackupArgs = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + Extra arguments passed to restic backup. + ''; + example = [ "--exclude-file=/etc/nixos/restic-ignore" ]; + }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + Extra extended options to be passed to the restic --option flag. + ''; + example = [ "sftp.command='ssh backup@192.168.1.100 -i /home/user/.ssh/id_rsa -s sftp'" ]; + }; + + initialize = mkOption { + type = types.bool; + default = false; + description = '' + Create the repository if it doesn't exist. + ''; + }; + + pruneOpts = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + A list of options (--keep-\* et al.) for 'restic forget + --prune', to automatically prune old snapshots. The + 'forget' command is run *after* the 'backup' command, so + keep that in mind when constructing the --keep-\* options. + ''; + example = [ + "--keep-daily 7" + "--keep-weekly 5" + "--keep-monthly 12" + "--keep-yearly 75" + ]; + }; + + runCheck = mkOption { + type = types.bool; + default = (builtins.length config.pub-solar-os.backups.backups.${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; + }; + + checkOpts = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + A list of options for 'restic check'. + ''; + example = [ "--with-cache" ]; + }; + + dynamicFilesFrom = mkOption { + type = with types; nullOr str; + default = null; + description = '' + A script that produces a list of files to back up. The + results of this command are given to the '--files-from' + option. The result is merged with paths specified via `paths`. + ''; + example = "find /home/matt/git -type d -name .git"; + }; + + backupPrepareCommand = mkOption { + type = with types; nullOr str; + default = null; + description = '' + A script that must run before starting the backup process. + ''; + }; + + backupCleanupCommand = mkOption { + type = with types; nullOr str; + default = null; + description = '' + A script that must run after finishing the backup process. + ''; + }; + + package = mkPackageOption pkgs "restic" { }; + + createWrapper = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to generate and add a script to the system path, that has the same environment variables set + as the systemd service. This can be used to e.g. mount snapshots or perform other opterations, without + having to manually specify most options. + ''; + }; + }; + } + ) + ); + default = { }; + example = { + localbackup = { + paths = [ "/home" ]; + exclude = [ "/home/*/.cache" ]; + initialize = true; + }; + remotebackup = { + paths = [ "/home" ]; + extraOptions = [ + "sftp.command='ssh backup@host -i /etc/nixos/secrets/backup-private-key -s sftp'" + ]; + timerConfig = { + OnCalendar = "00:05"; + RandomizedDelaySec = "5h"; }; }; }; + }; }; config = { services.restic.backups = let - stores = config.pub-solar-os.backups.stores; + repos = config.pub-solar-os.backups.repos; backups = config.pub-solar-os.backups.backups; - storeNames = builtins.attrNames stores; + storeNames = builtins.attrNames repos; backupNames = builtins.attrNames backups; createBackups = backupName: map (storeName: { name = "${backupName}-${storeName}"; - value = stores."${storeName}" // backups."${backupName}"; + value = repos."${storeName}" // backups."${backupName}"; }) storeNames; in diff --git a/tests/keycloak.nix b/tests/keycloak.nix index 7c02565..251707a 100644 --- a/tests/keycloak.nix +++ b/tests/keycloak.nix @@ -83,9 +83,12 @@ in wmClass = su "${gdbus} ${gseval} global.display.focus_window.wm_class"; in '' +<<<<<<< HEAD def puppeteer_run(cmd): client.succeed(f'puppeteer-run \'{cmd}\' ') +======= +>>>>>>> main start_all() nachtigall.wait_for_unit("system.slice") @@ -96,6 +99,7 @@ in nachtigall.wait_until_succeeds("curl https://auth.test.pub.solar/") client.wait_for_unit("system.slice") +<<<<<<< HEAD client.wait_for_file("/tmp/puppeteer.sock") puppeteer_run('page.goto("https://auth.test.pub.solar")') puppeteer_run('page.waitForNetworkIdle()') @@ -114,5 +118,10 @@ in puppeteer_run('page.locator("button::-p-text(Register)").click()') puppeteer_run('page.waitForNetworkIdle()') client.screenshot("after-register") +======= + client.sleep(30) + # client.wait_until_succeeds("${wmClass} | grep -q 'firefox'") + client.screenshot("screen") +>>>>>>> main ''; }