From 47dffd2a2f6f8db4b6aa3ef7a1b7143f3012cca6 Mon Sep 17 00:00:00 2001 From: Pierre Penninckx Date: Tue, 26 Nov 2024 20:59:07 +0100 Subject: [PATCH] switch backup contract to new contract style (#367) Co-authored-by: ibizaman --- docs/redirects.json | 111 ++++++++---- lib/default.nix | 4 +- modules/blocks/ldap.nix | 34 ++-- modules/blocks/restic.nix | 36 +--- modules/contracts/backup.nix | 211 ++++++++++++++++------- modules/contracts/backup/dummyModule.nix | 21 +-- modules/contracts/default.nix | 2 +- modules/services/arr.nix | 30 +--- modules/services/audiobookshelf.nix | 28 +-- modules/services/deluge.nix | 28 +-- modules/services/forgejo.nix | 32 ++-- modules/services/grocy.nix | 27 +-- modules/services/hledger.nix | 28 +-- modules/services/home-assistant.nix | 30 +--- modules/services/jellyfin.nix | 28 +-- modules/services/nextcloud-server.nix | 30 +--- modules/services/vaultwarden.nix | 32 ++-- test/blocks/postgresql.nix | 2 +- test/services/vaultwarden.nix | 2 +- 19 files changed, 336 insertions(+), 380 deletions(-) diff --git a/docs/redirects.json b/docs/redirects.json index 4cbae29..3e19ac8 100644 --- a/docs/redirects.json +++ b/docs/redirects.json @@ -602,6 +602,9 @@ "contracts-backup-options-shb.contracts.backup.result.restoreScript": [ "contracts-backup.html#contracts-backup-options-shb.contracts.backup.result.restoreScript" ], + "contracts-backup-options-shb.contracts.backup.settings": [ + "contracts-backup.html#contracts-backup-options-shb.contracts.backup.settings" + ], "contracts-databasebackup-options-shb.contracts.databasebackup": [ "contracts-databasebackup.html#contracts-databasebackup-options-shb.contracts.databasebackup" ], @@ -851,23 +854,35 @@ "services-forgejo-options-shb.forgejo.backup": [ "services-forgejo.html#services-forgejo-options-shb.forgejo.backup" ], - "services-forgejo-options-shb.forgejo.backup.excludePatterns": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.excludePatterns" + "services-forgejo-options-shb.forgejo.backup.request": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request" ], - "services-forgejo-options-shb.forgejo.backup.hooks": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.hooks" + "services-forgejo-options-shb.forgejo.backup.request.excludePatterns": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.excludePatterns" ], - "services-forgejo-options-shb.forgejo.backup.hooks.afterBackup": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.hooks.afterBackup" + "services-forgejo-options-shb.forgejo.backup.request.hooks": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.hooks" ], - "services-forgejo-options-shb.forgejo.backup.hooks.beforeBackup": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.hooks.beforeBackup" + "services-forgejo-options-shb.forgejo.backup.request.hooks.afterBackup": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.hooks.afterBackup" ], - "services-forgejo-options-shb.forgejo.backup.sourceDirectories": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.sourceDirectories" + "services-forgejo-options-shb.forgejo.backup.request.hooks.beforeBackup": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.hooks.beforeBackup" ], - "services-forgejo-options-shb.forgejo.backup.user": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.user" + "services-forgejo-options-shb.forgejo.backup.request.sourceDirectories": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.sourceDirectories" + ], + "services-forgejo-options-shb.forgejo.backup.request.user": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.user" + ], + "services-forgejo-options-shb.forgejo.backup.result": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.result" + ], + "services-forgejo-options-shb.forgejo.backup.result.backupService": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.result.backupService" + ], + "services-forgejo-options-shb.forgejo.backup.result.restoreScript": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.backup.result.restoreScript" ], "services-forgejo-options-shb.forgejo.databasePassword": [ "services-forgejo.html#services-forgejo-options-shb.forgejo.databasePassword" @@ -1325,23 +1340,35 @@ "services-nextcloudserver-options-shb.nextcloud.backup": [ "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup" ], - "services-nextcloudserver-options-shb.nextcloud.backup.excludePatterns": [ - "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.excludePatterns" + "services-nextcloudserver-options-shb.nextcloud.backup.request": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request" ], - "services-nextcloudserver-options-shb.nextcloud.backup.hooks": [ - "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.hooks" + "services-nextcloudserver-options-shb.nextcloud.backup.request.excludePatterns": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.excludePatterns" ], - "services-nextcloudserver-options-shb.nextcloud.backup.hooks.afterBackup": [ - "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.hooks.afterBackup" + "services-nextcloudserver-options-shb.nextcloud.backup.request.hooks": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.hooks" ], - "services-nextcloudserver-options-shb.nextcloud.backup.hooks.beforeBackup": [ - "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.hooks.beforeBackup" + "services-nextcloudserver-options-shb.nextcloud.backup.request.hooks.afterBackup": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.hooks.afterBackup" ], - "services-nextcloudserver-options-shb.nextcloud.backup.sourceDirectories": [ - "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.sourceDirectories" + "services-nextcloudserver-options-shb.nextcloud.backup.request.hooks.beforeBackup": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.hooks.beforeBackup" ], - "services-nextcloudserver-options-shb.nextcloud.backup.user": [ - "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.user" + "services-nextcloudserver-options-shb.nextcloud.backup.request.sourceDirectories": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.sourceDirectories" + ], + "services-nextcloudserver-options-shb.nextcloud.backup.request.user": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.user" + ], + "services-nextcloudserver-options-shb.nextcloud.backup.result": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.result" + ], + "services-nextcloudserver-options-shb.nextcloud.backup.result.backupService": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.result.backupService" + ], + "services-nextcloudserver-options-shb.nextcloud.backup.result.restoreScript": [ + "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.result.restoreScript" ], "services-nextcloudserver-options-shb.nextcloud.dataDir": [ "services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.dataDir" @@ -1475,23 +1502,35 @@ "services-vaultwarden-options-shb.vaultwarden.backup": [ "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup" ], - "services-vaultwarden-options-shb.vaultwarden.backup.excludePatterns": [ - "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.excludePatterns" + "services-vaultwarden-options-shb.vaultwarden.backup.request": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request" ], - "services-vaultwarden-options-shb.vaultwarden.backup.hooks": [ - "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.hooks" + "services-vaultwarden-options-shb.vaultwarden.backup.request.excludePatterns": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.excludePatterns" ], - "services-vaultwarden-options-shb.vaultwarden.backup.hooks.afterBackup": [ - "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.hooks.afterBackup" + "services-vaultwarden-options-shb.vaultwarden.backup.request.hooks": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.hooks" ], - "services-vaultwarden-options-shb.vaultwarden.backup.hooks.beforeBackup": [ - "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.hooks.beforeBackup" + "services-vaultwarden-options-shb.vaultwarden.backup.request.hooks.afterBackup": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.hooks.afterBackup" ], - "services-vaultwarden-options-shb.vaultwarden.backup.sourceDirectories": [ - "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.sourceDirectories" + "services-vaultwarden-options-shb.vaultwarden.backup.request.hooks.beforeBackup": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.hooks.beforeBackup" ], - "services-vaultwarden-options-shb.vaultwarden.backup.user": [ - "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.user" + "services-vaultwarden-options-shb.vaultwarden.backup.request.sourceDirectories": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.sourceDirectories" + ], + "services-vaultwarden-options-shb.vaultwarden.backup.request.user": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.user" + ], + "services-vaultwarden-options-shb.vaultwarden.backup.result": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.result" + ], + "services-vaultwarden-options-shb.vaultwarden.backup.result.backupService": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.result.backupService" + ], + "services-vaultwarden-options-shb.vaultwarden.backup.result.restoreScript": [ + "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.result.restoreScript" ], "services-vaultwarden-options-shb.vaultwarden.databasePassword": [ "services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.databasePassword" diff --git a/lib/default.nix b/lib/default.nix index 9350a52..978628c 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,7 +1,7 @@ { pkgs, lib }: let inherit (builtins) isAttrs hasAttr; - inherit (lib) concatMapStringsSep concatStringsSep mapAttrsToList; + inherit (lib) any concatMapStringsSep concatStringsSep mapAttrsToList; in rec { # Replace secrets in a file. @@ -292,4 +292,6 @@ rec { "${concatStringsSep "_" secret.path}:${secret.${sourceField}}"; in map genLoadCredentials allSecrets; + + anyNotNull = any (x: x != null); } diff --git a/modules/blocks/ldap.nix b/modules/blocks/ldap.nix index ef2ed61..bda49e4 100644 --- a/modules/blocks/ldap.nix +++ b/modules/blocks/ldap.nix @@ -103,31 +103,19 @@ in }; backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."lldap" = { - request = config.shb.lldap.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; - readOnly = true; - default = { - # TODO: is there a workaround that avoid needing to use root? - # root because otherwise we cannot access the private StateDiretory - user = "root"; - # /private because the systemd service uses DynamicUser=true - sourceDirectories = [ - "/var/lib/private/lldap" - ]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + # TODO: is there a workaround that avoid needing to use root? + # root because otherwise we cannot access the private StateDiretory + user = "root"; + # /private because the systemd service uses DynamicUser=true + sourceDirectories = [ + "/var/lib/private/lldap" + ]; + }; }; }; }; diff --git a/modules/blocks/restic.nix b/modules/blocks/restic.nix index 314d9ff..6d38e8e 100644 --- a/modules/blocks/restic.nix +++ b/modules/blocks/restic.nix @@ -111,17 +111,7 @@ in description = "Files to backup following the [backup contract](./contracts-backup.html)."; default = {}; type = attrsOf (submodule ({ name, config, ... }: { - options = { - request = mkOption { - description = '' - Request part of the backup contract. - - Accepts values from a requester. - ''; - - type = contracts.backup.request; - }; - + options = contracts.backup.mkProvider { settings = mkOption { description = '' Settings specific to the Restic provider. @@ -132,26 +122,12 @@ in }; }; - result = mkOption { - description = '' - Result part of the backup contract. + resultCfg = { + restoreScript = fullName name config.settings.repository; + restoreScriptText = "${fullName "" { path = "path/to/repository"; }}"; - Contains the output of the Restic provider. - ''; - default = { - restoreScript = fullName name config.settings.repository; - backupService = "${fullName name config.settings.repository}.service"; - }; - defaultText = { - restoreScriptText = "${fullName "" { path = "path/to/repository"; }}"; - backupServiceText = "${fullName "" { path = "path/to/repository"; }}.service"; - }; - type = contracts.backup.result { - restoreScript = fullName name config.settings.repository; - backupService = "${fullName name config.settings.repository}.service"; - restoreScriptText = "${fullName "" { path = "path/to/repository"; }}"; - backupServiceText = "${fullName "" { path = "path/to/repository"; }}.service"; - }; + backupService = "${fullName name config.settings.repository}.service"; + backupServiceText = "${fullName "" { path = "path/to/repository"; }}.service"; }; }; })); diff --git a/modules/contracts/backup.nix b/modules/contracts/backup.nix index 74040d9..4fbd7e8 100644 --- a/modules/contracts/backup.nix +++ b/modules/contracts/backup.nix @@ -1,91 +1,174 @@ -{ lib, ... }: +{ pkgs, lib, ... }: let - inherit (lib) mkOption; + inherit (lib) concatStringsSep literalMD mkOption optionalAttrs optionalString; inherit (lib.types) listOf nonEmptyListOf submodule str; + + shblib = pkgs.callPackage ../../lib {}; + inherit (shblib) anyNotNull; in { - request = submodule { - options = { - user = mkOption { - description = '' - Unix user doing the backups. - ''; - type = str; + mkRequest = + { user ? "", + userText ? null, + sourceDirectories ? [ "/var/lib/example" ], + sourceDirectoriesText ? null, + excludePatterns ? [], + excludePatternsText ? null, + beforeBackup ? [], + beforeBackupText ? null, + afterBackup ? [], + afterBackupText ? null, + }: mkOption { + description = '' + Request part of the backup contract. + + Options set by the requester module + enforcing how to backup files. + ''; + + default = { + inherit user sourceDirectories excludePatterns; + hooks = { + inherit beforeBackup afterBackup; + }; }; - sourceDirectories = mkOption { - description = "Directories to backup."; - type = nonEmptyListOf str; + defaultText = optionalString (anyNotNull [ + userText + sourceDirectoriesText + excludePatternsText + beforeBackupText + afterBackupText + ]) (literalMD '' + { + user = ${if userText != null then userText else user}; + sourceDirectories = ${if sourceDirectoriesText != null then sourceDirectoriesText else "[ " + concatStringsSep " " sourceDirectories + " ]"}; + excludePatterns = ${if excludePatternsText != null then excludePatternsText else "[ " + concatStringsSep " " excludePatterns + " ]"}; + hooks.beforeBackup = ${if beforeBackupText != null then beforeBackupText else "[ " + concatStringsSep " " beforeBackup + " ]"}; + hooks.afterBackup = ${if afterBackupText != null then afterBackupText else "[ " + concatStringsSep " " afterBackup + " ]"}; }; + ''); - excludePatterns = mkOption { - description = "File patterns to exclude."; - type = listOf str; - default = []; - }; + type = submodule { + options = { + user = mkOption { + description = '' + Unix user doing the backups. + ''; + type = str; + example = "vaultwarden"; + default = user; + } // optionalAttrs (userText != null) { + defaultText = literalMD userText; + }; - hooks = mkOption { - description = "Hooks to run around the backup."; - default = {}; - type = submodule { - options = { - beforeBackup = mkOption { - description = "Hooks to run before backup."; - type = listOf str; - default = []; - }; + sourceDirectories = mkOption { + description = "Directories to backup."; + type = nonEmptyListOf str; + example = "/var/lib/vaultwarden"; + default = sourceDirectories; + } // optionalAttrs (sourceDirectoriesText != null) { + defaultText = literalMD sourceDirectoriesText; + }; - afterBackup = mkOption { - description = "Hooks to run after backup."; - type = listOf str; - default = []; + excludePatterns = mkOption { + description = "File patterns to exclude."; + type = listOf str; + default = excludePatterns; + } // optionalAttrs (excludePatternsText != null) { + defaultText = literalMD excludePatternsText; + }; + + hooks = mkOption { + description = "Hooks to run around the backup."; + default = {}; + type = submodule { + options = { + beforeBackup = mkOption { + description = "Hooks to run before backup."; + type = listOf str; + default = beforeBackup; + } // optionalAttrs (beforeBackupText != null) { + defaultText = literalMD beforeBackupText; + }; + + afterBackup = mkOption { + description = "Hooks to run after backup."; + type = listOf str; + default = afterBackup; + } // optionalAttrs (afterBackupText != null) { + defaultText = literalMD afterBackupText; + }; + }; }; }; }; }; }; - }; - result = { - restoreScript, + mkResult = { + restoreScript ? "restore", restoreScriptText ? null, - backupService, + backupService ? "backup.service", backupServiceText ? null, - }: submodule { - options = { - restoreScript = mkOption { - description = '' - Name of script that can restore the database. - One can then list snapshots with: + }: mkOption { + description = '' + Result part of the backup contract. - ```bash - $ ${if restoreScriptText != null then restoreScriptText else restoreScript} snapshots - ``` + Options set by the provider module that indicates the name of the backup and restor scripts. + ''; + default = { + inherit restoreScript backupService; + }; - And restore the database with: + defaultText = optionalString (anyNotNull [ + restoreScriptText + backupServiceText + ]) (literalMD '' + { + restoreScript = ${if restoreScriptText != null then restoreScriptText else restoreScript}; + backupService = ${if backupServiceText != null then backupServiceText else backupService}; + } + ''); - ```bash - $ ${if restoreScriptText != null then restoreScriptText else restoreScript} restore latest - ``` - ''; - type = str; - default = restoreScript; - defaultText = restoreScriptText; - }; + type = submodule { + options = { + restoreScript = mkOption { + description = '' + Name of script that can restore the database. + One can then list snapshots with: - backupService = mkOption { - description = '' - Name of service backing up the database. + ```bash + $ ${if restoreScriptText != null then restoreScriptText else restoreScript} snapshots + ``` - This script can be ran manually to backup the database: + And restore the database with: - ```bash - $ systemctl start ${if backupServiceText != null then backupServiceText else backupService} - ``` - ''; - type = str; - default = backupService; - defaultText = backupServiceText; + ```bash + $ ${if restoreScriptText != null then restoreScriptText else restoreScript} restore latest + ``` + ''; + type = str; + default = restoreScript; + } // optionalAttrs (restoreScriptText != null) { + defaultText = literalMD restoreScriptText; + }; + + backupService = mkOption { + description = '' + Name of service backing up the database. + + This script can be ran manually to backup the database: + + ```bash + $ systemctl start ${if backupServiceText != null then backupServiceText else backupService} + ``` + ''; + type = str; + default = backupService; + } // optionalAttrs (backupServiceText != null) { + defaultText = literalMD backupServiceText; + }; }; }; }; diff --git a/modules/contracts/backup/dummyModule.nix b/modules/contracts/backup/dummyModule.nix index 2d77984..004f44f 100644 --- a/modules/contracts/backup/dummyModule.nix +++ b/modules/contracts/backup/dummyModule.nix @@ -3,7 +3,7 @@ let contracts = pkgs.callPackage ../. {}; inherit (lib) mkOption; - inherit (lib.types) anything submodule; + inherit (lib.types) submodule; in { options.shb.contracts.backup = mkOption { @@ -23,24 +23,7 @@ in ''; type = submodule { - options = { - request = mkOption { - description = '' - Options set by a requester module of the backup contract. - ''; - type = contracts.backup.request; - }; - - result = mkOption { - description = '' - Options set by a provider module of the backup contract. - ''; - type = contracts.backup.result { - restoreScript = "my_restore_script"; - backupService = "my_backup_service.service"; - }; - }; - }; + options = contracts.backup.contract; }; }; } diff --git a/modules/contracts/default.nix b/modules/contracts/default.nix index 46140d4..1c0642d 100644 --- a/modules/contracts/default.nix +++ b/modules/contracts/default.nix @@ -48,7 +48,7 @@ in inherit mkContractFunctions; databasebackup = import ./databasebackup.nix { inherit lib; }; - backup = import ./backup.nix { inherit lib; }; + backup = importContract ./backup.nix; mount = import ./mount.nix { inherit lib; }; secret = importContract ./secret.nix; ssl = import ./ssl.nix { inherit lib; }; diff --git a/modules/services/arr.nix b/modules/services/arr.nix index ca17b31..f5c58ea 100644 --- a/modules/services/arr.nix +++ b/modules/services/arr.nix @@ -316,29 +316,17 @@ let }; backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."${name}" = { - request = config.shb.${name}.backup; - settings = { - enable = true; - }; - } - ``` + Backup configuration. ''; - readOnly = true; - default = { - user = name; - sourceDirectories = [ - cfg.${name}.dataDir - ]; - excludePatterns = [".db-shm" ".db-wal" ".mono"]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = name; + sourceDirectories = [ + cfg.${name}.dataDir + ]; + excludePatterns = [".db-shm" ".db-wal" ".mono"]; + }; }; }; } // (c.moreOptions or {}); diff --git a/modules/services/audiobookshelf.nix b/modules/services/audiobookshelf.nix index 29ee5dd..b69758e 100644 --- a/modules/services/audiobookshelf.nix +++ b/modules/services/audiobookshelf.nix @@ -88,28 +88,16 @@ in }; backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."audiobookshelf" = { - request = config.shb.audiobookshelf.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; - readOnly = true; - default = { - user = "audiobookshelf"; - sourceDirectories = [ - "/var/lib/audiobookshelf" - ]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = "audiobookshelf"; + sourceDirectories = [ + "/var/lib/audiobookshelf" + ]; + }; }; }; diff --git a/modules/services/deluge.nix b/modules/services/deluge.nix index cf69d51..11256b1 100644 --- a/modules/services/deluge.nix +++ b/modules/services/deluge.nix @@ -244,28 +244,16 @@ in }; backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."vaultwarden" = { - request = config.shb.vaultwarden.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; - readOnly = true; - default = { - user = "deluge"; - sourceDirectories = [ - cfg.dataDir - ]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = "deluge"; + sourceDirectories = [ + cfg.dataDir + ]; + }; }; }; diff --git a/modules/services/forgejo.nix b/modules/services/forgejo.nix index 894373e..3d5b1cb 100644 --- a/modules/services/forgejo.nix +++ b/modules/services/forgejo.nix @@ -241,30 +241,18 @@ in }; backup = mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."forgejo" = { - request = config.shb.forgejo.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; - readOnly = true; - default = { - user = options.services.forgejo.user.value; - sourceDirectories = [ - options.services.forgejo.dump.backupDir.value - ] ++ optionals (cfg.repositoryRoot != null) [ - cfg.repositoryRoot - ]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = options.services.forgejo.user.value; + sourceDirectories = [ + options.services.forgejo.dump.backupDir.value + ] ++ optionals (cfg.repositoryRoot != null) [ + cfg.repositoryRoot + ]; + }; }; }; diff --git a/modules/services/grocy.nix b/modules/services/grocy.nix index e1dc3bb..8d4b36e 100644 --- a/modules/services/grocy.nix +++ b/modules/services/grocy.nix @@ -63,28 +63,17 @@ in }; backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."grocy" = { - request = config.shb.grocy.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; readOnly = true; - default = { - user = "grocy"; - sourceDirectories = [ - cfg.dataDir - ]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = "grocy"; + sourceDirectories = [ + cfg.dataDir + ]; + }; }; }; diff --git a/modules/services/hledger.nix b/modules/services/hledger.nix index ee4c3c9..99bbd03 100644 --- a/modules/services/hledger.nix +++ b/modules/services/hledger.nix @@ -55,28 +55,16 @@ in }; backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."hledger" = { - request = config.shb.hledger.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; - readOnly = true; - default = { - user = "hledger"; - sourceDirectories = [ - cfg.dataDir - ]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = "hledger"; + sourceDirectories = [ + cfg.dataDir + ]; + }; }; }; }; diff --git a/modules/services/home-assistant.nix b/modules/services/home-assistant.nix index 43214a4..8f2189f 100644 --- a/modules/services/home-assistant.nix +++ b/modules/services/home-assistant.nix @@ -140,29 +140,17 @@ in }; backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."home-assistant" = { - request = config.shb.home-assistant.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; - readOnly = true; - default = { - user = "hass"; - # No need for backup hooks as we use an hourly automation job in home assistant directly with a cron job. - sourceDirectories = [ - "/var/lib/hass/backups" - ]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = "hass"; + # No need for backup hooks as we use an hourly automation job in home assistant directly with a cron job. + sourceDirectories = [ + "/var/lib/hass/backups" + ]; + }; }; }; }; diff --git a/modules/services/jellyfin.nix b/modules/services/jellyfin.nix index 40cd697..adaeef8 100644 --- a/modules/services/jellyfin.nix +++ b/modules/services/jellyfin.nix @@ -151,28 +151,16 @@ in }; backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."jellyfin" = { - request = config.shb.jellyfin.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; - readOnly = true; - default = { - user = "jellyfin"; - sourceDirectories = [ - "/var/lib/jellyfin" - ]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = "jellyfin"; + sourceDirectories = [ + "/var/lib/jellyfin" + ]; + }; }; }; }; diff --git a/modules/services/nextcloud-server.nix b/modules/services/nextcloud-server.nix index 426fddc..c0fed18 100644 --- a/modules/services/nextcloud-server.nix +++ b/modules/services/nextcloud-server.nix @@ -519,29 +519,17 @@ in backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."nextcloud" = { - request = config.shb.nextcloud.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; - readOnly = true; - default = { - user = "nextcloud"; - sourceDirectories = [ - cfg.dataDir - ]; - excludePatterns = [".rnd"]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = "nextcloud"; + sourceDirectories = [ + cfg.dataDir + ]; + excludePatterns = [".rnd"]; + }; }; }; diff --git a/modules/services/vaultwarden.nix b/modules/services/vaultwarden.nix index 680fbeb..2579a60 100644 --- a/modules/services/vaultwarden.nix +++ b/modules/services/vaultwarden.nix @@ -128,28 +128,16 @@ in }; backup = lib.mkOption { - type = contracts.backup.request; description = '' - Backup configuration. This is an output option. - - Use it to initialize a block implementing the "backup" contract. - For example, with the restic block: - - ``` - shb.restic.instances."vaultwarden" = { - request = config.shb.vaultwarden.backup; - settings = { - enable = true; - }; - }; - ``` + Backup configuration. ''; - readOnly = true; - default = { - user = "vaultwarden"; - sourceDirectories = [ - dataFolder - ]; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = "vaultwarden"; + sourceDirectories = [ + dataFolder + ]; + }; }; }; @@ -162,6 +150,10 @@ in }; config = lib.mkIf cfg.enable { + # Seems superfluous but otherwise we get: + # The option `shb.vaultwarden.backup' was accessed but has no value defined. + shb.vaultwarden.backup = {}; + services.vaultwarden = { enable = true; dbBackend = "postgresql"; diff --git a/test/blocks/postgresql.nix b/test/blocks/postgresql.nix index 9bd0163..fed7fb9 100644 --- a/test/blocks/postgresql.nix +++ b/test/blocks/postgresql.nix @@ -1,4 +1,4 @@ -{ pkgs, lib, ... }: +{ pkgs, ... }: let pkgs' = pkgs; in diff --git a/test/services/vaultwarden.nix b/test/services/vaultwarden.nix index 1b5ea2c..95a16c6 100644 --- a/test/services/vaultwarden.nix +++ b/test/services/vaultwarden.nix @@ -99,7 +99,7 @@ let ../../modules/blocks/restic.nix ]; shb.restic.instances."testinstance" = { - request = config.shb.vaultwarden.backup; + request = config.shb.vaultwarden.backup.request; settings = { enable = true; passphrase.result = config.shb.hardcodedsecret.backupPassphrase.result;