switch backup contract to new contract style (#367)
Co-authored-by: ibizaman <ibizapeanut@gmail.com>
This commit is contained in:
parent
ba1e60a45e
commit
47dffd2a2f
19 changed files with 336 additions and 380 deletions
|
|
@ -602,6 +602,9 @@
|
||||||
"contracts-backup-options-shb.contracts.backup.result.restoreScript": [
|
"contracts-backup-options-shb.contracts.backup.result.restoreScript": [
|
||||||
"contracts-backup.html#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-options-shb.contracts.databasebackup": [
|
||||||
"contracts-databasebackup.html#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-options-shb.forgejo.backup": [
|
||||||
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup"
|
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup"
|
||||||
],
|
],
|
||||||
"services-forgejo-options-shb.forgejo.backup.excludePatterns": [
|
"services-forgejo-options-shb.forgejo.backup.request": [
|
||||||
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup.excludePatterns"
|
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request"
|
||||||
],
|
],
|
||||||
"services-forgejo-options-shb.forgejo.backup.hooks": [
|
"services-forgejo-options-shb.forgejo.backup.request.excludePatterns": [
|
||||||
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup.hooks"
|
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.excludePatterns"
|
||||||
],
|
],
|
||||||
"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.hooks.afterBackup"
|
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.hooks"
|
||||||
],
|
],
|
||||||
"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.hooks.beforeBackup"
|
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.hooks.afterBackup"
|
||||||
],
|
],
|
||||||
"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.sourceDirectories"
|
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup.request.hooks.beforeBackup"
|
||||||
],
|
],
|
||||||
"services-forgejo-options-shb.forgejo.backup.user": [
|
"services-forgejo-options-shb.forgejo.backup.request.sourceDirectories": [
|
||||||
"services-forgejo.html#services-forgejo-options-shb.forgejo.backup.user"
|
"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-options-shb.forgejo.databasePassword": [
|
||||||
"services-forgejo.html#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-nextcloudserver-options-shb.nextcloud.backup": [
|
||||||
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup"
|
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup"
|
||||||
],
|
],
|
||||||
"services-nextcloudserver-options-shb.nextcloud.backup.excludePatterns": [
|
"services-nextcloudserver-options-shb.nextcloud.backup.request": [
|
||||||
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.excludePatterns"
|
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request"
|
||||||
],
|
],
|
||||||
"services-nextcloudserver-options-shb.nextcloud.backup.hooks": [
|
"services-nextcloudserver-options-shb.nextcloud.backup.request.excludePatterns": [
|
||||||
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.hooks"
|
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.excludePatterns"
|
||||||
],
|
],
|
||||||
"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.hooks.afterBackup"
|
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.hooks"
|
||||||
],
|
],
|
||||||
"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.hooks.beforeBackup"
|
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.hooks.afterBackup"
|
||||||
],
|
],
|
||||||
"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.sourceDirectories"
|
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.request.hooks.beforeBackup"
|
||||||
],
|
],
|
||||||
"services-nextcloudserver-options-shb.nextcloud.backup.user": [
|
"services-nextcloudserver-options-shb.nextcloud.backup.request.sourceDirectories": [
|
||||||
"services-nextcloud.html#services-nextcloudserver-options-shb.nextcloud.backup.user"
|
"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-nextcloudserver-options-shb.nextcloud.dataDir": [
|
||||||
"services-nextcloud.html#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-options-shb.vaultwarden.backup": [
|
||||||
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup"
|
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup"
|
||||||
],
|
],
|
||||||
"services-vaultwarden-options-shb.vaultwarden.backup.excludePatterns": [
|
"services-vaultwarden-options-shb.vaultwarden.backup.request": [
|
||||||
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.excludePatterns"
|
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request"
|
||||||
],
|
],
|
||||||
"services-vaultwarden-options-shb.vaultwarden.backup.hooks": [
|
"services-vaultwarden-options-shb.vaultwarden.backup.request.excludePatterns": [
|
||||||
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.hooks"
|
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.excludePatterns"
|
||||||
],
|
],
|
||||||
"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.hooks.afterBackup"
|
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.hooks"
|
||||||
],
|
],
|
||||||
"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.hooks.beforeBackup"
|
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.hooks.afterBackup"
|
||||||
],
|
],
|
||||||
"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.sourceDirectories"
|
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.request.hooks.beforeBackup"
|
||||||
],
|
],
|
||||||
"services-vaultwarden-options-shb.vaultwarden.backup.user": [
|
"services-vaultwarden-options-shb.vaultwarden.backup.request.sourceDirectories": [
|
||||||
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.backup.user"
|
"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-options-shb.vaultwarden.databasePassword": [
|
||||||
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.databasePassword"
|
"services-vaultwarden.html#services-vaultwarden-options-shb.vaultwarden.databasePassword"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{ pkgs, lib }:
|
{ pkgs, lib }:
|
||||||
let
|
let
|
||||||
inherit (builtins) isAttrs hasAttr;
|
inherit (builtins) isAttrs hasAttr;
|
||||||
inherit (lib) concatMapStringsSep concatStringsSep mapAttrsToList;
|
inherit (lib) any concatMapStringsSep concatStringsSep mapAttrsToList;
|
||||||
in
|
in
|
||||||
rec {
|
rec {
|
||||||
# Replace secrets in a file.
|
# Replace secrets in a file.
|
||||||
|
|
@ -292,4 +292,6 @@ rec {
|
||||||
"${concatStringsSep "_" secret.path}:${secret.${sourceField}}";
|
"${concatStringsSep "_" secret.path}:${secret.${sourceField}}";
|
||||||
in
|
in
|
||||||
map genLoadCredentials allSecrets;
|
map genLoadCredentials allSecrets;
|
||||||
|
|
||||||
|
anyNotNull = any (x: x != null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,31 +103,19 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
# TODO: is there a workaround that avoid needing to use root?
|
# TODO: is there a workaround that avoid needing to use root?
|
||||||
# root because otherwise we cannot access the private StateDiretory
|
# root because otherwise we cannot access the private StateDiretory
|
||||||
user = "root";
|
user = "root";
|
||||||
# /private because the systemd service uses DynamicUser=true
|
# /private because the systemd service uses DynamicUser=true
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
"/var/lib/private/lldap"
|
"/var/lib/private/lldap"
|
||||||
];
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -111,17 +111,7 @@ in
|
||||||
description = "Files to backup following the [backup contract](./contracts-backup.html).";
|
description = "Files to backup following the [backup contract](./contracts-backup.html).";
|
||||||
default = {};
|
default = {};
|
||||||
type = attrsOf (submodule ({ name, config, ... }: {
|
type = attrsOf (submodule ({ name, config, ... }: {
|
||||||
options = {
|
options = contracts.backup.mkProvider {
|
||||||
request = mkOption {
|
|
||||||
description = ''
|
|
||||||
Request part of the backup contract.
|
|
||||||
|
|
||||||
Accepts values from a requester.
|
|
||||||
'';
|
|
||||||
|
|
||||||
type = contracts.backup.request;
|
|
||||||
};
|
|
||||||
|
|
||||||
settings = mkOption {
|
settings = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
Settings specific to the Restic provider.
|
Settings specific to the Restic provider.
|
||||||
|
|
@ -132,26 +122,12 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
result = mkOption {
|
resultCfg = {
|
||||||
description = ''
|
restoreScript = fullName name config.settings.repository;
|
||||||
Result part of the backup contract.
|
restoreScriptText = "${fullName "<name>" { path = "path/to/repository"; }}";
|
||||||
|
|
||||||
Contains the output of the Restic provider.
|
backupService = "${fullName name config.settings.repository}.service";
|
||||||
'';
|
backupServiceText = "${fullName "<name>" { path = "path/to/repository"; }}.service";
|
||||||
default = {
|
|
||||||
restoreScript = fullName name config.settings.repository;
|
|
||||||
backupService = "${fullName name config.settings.repository}.service";
|
|
||||||
};
|
|
||||||
defaultText = {
|
|
||||||
restoreScriptText = "${fullName "<name>" { path = "path/to/repository"; }}";
|
|
||||||
backupServiceText = "${fullName "<name>" { path = "path/to/repository"; }}.service";
|
|
||||||
};
|
|
||||||
type = contracts.backup.result {
|
|
||||||
restoreScript = fullName name config.settings.repository;
|
|
||||||
backupService = "${fullName name config.settings.repository}.service";
|
|
||||||
restoreScriptText = "${fullName "<name>" { path = "path/to/repository"; }}";
|
|
||||||
backupServiceText = "${fullName "<name>" { path = "path/to/repository"; }}.service";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -1,91 +1,174 @@
|
||||||
{ lib, ... }:
|
{ pkgs, lib, ... }:
|
||||||
let
|
let
|
||||||
inherit (lib) mkOption;
|
inherit (lib) concatStringsSep literalMD mkOption optionalAttrs optionalString;
|
||||||
inherit (lib.types) listOf nonEmptyListOf submodule str;
|
inherit (lib.types) listOf nonEmptyListOf submodule str;
|
||||||
|
|
||||||
|
shblib = pkgs.callPackage ../../lib {};
|
||||||
|
inherit (shblib) anyNotNull;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
request = submodule {
|
mkRequest =
|
||||||
options = {
|
{ user ? "",
|
||||||
user = mkOption {
|
userText ? null,
|
||||||
description = ''
|
sourceDirectories ? [ "/var/lib/example" ],
|
||||||
Unix user doing the backups.
|
sourceDirectoriesText ? null,
|
||||||
'';
|
excludePatterns ? [],
|
||||||
type = str;
|
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 {
|
defaultText = optionalString (anyNotNull [
|
||||||
description = "Directories to backup.";
|
userText
|
||||||
type = nonEmptyListOf str;
|
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 {
|
type = submodule {
|
||||||
description = "File patterns to exclude.";
|
options = {
|
||||||
type = listOf str;
|
user = mkOption {
|
||||||
default = [];
|
description = ''
|
||||||
};
|
Unix user doing the backups.
|
||||||
|
'';
|
||||||
|
type = str;
|
||||||
|
example = "vaultwarden";
|
||||||
|
default = user;
|
||||||
|
} // optionalAttrs (userText != null) {
|
||||||
|
defaultText = literalMD userText;
|
||||||
|
};
|
||||||
|
|
||||||
hooks = mkOption {
|
sourceDirectories = mkOption {
|
||||||
description = "Hooks to run around the backup.";
|
description = "Directories to backup.";
|
||||||
default = {};
|
type = nonEmptyListOf str;
|
||||||
type = submodule {
|
example = "/var/lib/vaultwarden";
|
||||||
options = {
|
default = sourceDirectories;
|
||||||
beforeBackup = mkOption {
|
} // optionalAttrs (sourceDirectoriesText != null) {
|
||||||
description = "Hooks to run before backup.";
|
defaultText = literalMD sourceDirectoriesText;
|
||||||
type = listOf str;
|
};
|
||||||
default = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
afterBackup = mkOption {
|
excludePatterns = mkOption {
|
||||||
description = "Hooks to run after backup.";
|
description = "File patterns to exclude.";
|
||||||
type = listOf str;
|
type = listOf str;
|
||||||
default = [];
|
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 = {
|
mkResult = {
|
||||||
restoreScript,
|
restoreScript ? "restore",
|
||||||
restoreScriptText ? null,
|
restoreScriptText ? null,
|
||||||
backupService,
|
backupService ? "backup.service",
|
||||||
backupServiceText ? null,
|
backupServiceText ? null,
|
||||||
}: submodule {
|
}: mkOption {
|
||||||
options = {
|
description = ''
|
||||||
restoreScript = mkOption {
|
Result part of the backup contract.
|
||||||
description = ''
|
|
||||||
Name of script that can restore the database.
|
|
||||||
One can then list snapshots with:
|
|
||||||
|
|
||||||
```bash
|
Options set by the provider module that indicates the name of the backup and restor scripts.
|
||||||
$ ${if restoreScriptText != null then restoreScriptText else restoreScript} snapshots
|
'';
|
||||||
```
|
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
|
type = submodule {
|
||||||
$ ${if restoreScriptText != null then restoreScriptText else restoreScript} restore latest
|
options = {
|
||||||
```
|
restoreScript = mkOption {
|
||||||
'';
|
description = ''
|
||||||
type = str;
|
Name of script that can restore the database.
|
||||||
default = restoreScript;
|
One can then list snapshots with:
|
||||||
defaultText = restoreScriptText;
|
|
||||||
};
|
|
||||||
|
|
||||||
backupService = mkOption {
|
```bash
|
||||||
description = ''
|
$ ${if restoreScriptText != null then restoreScriptText else restoreScript} snapshots
|
||||||
Name of service backing up the database.
|
```
|
||||||
|
|
||||||
This script can be ran manually to backup the database:
|
And restore the database with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ systemctl start ${if backupServiceText != null then backupServiceText else backupService}
|
$ ${if restoreScriptText != null then restoreScriptText else restoreScript} restore latest
|
||||||
```
|
```
|
||||||
'';
|
'';
|
||||||
type = str;
|
type = str;
|
||||||
default = backupService;
|
default = restoreScript;
|
||||||
defaultText = backupServiceText;
|
} // 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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ let
|
||||||
contracts = pkgs.callPackage ../. {};
|
contracts = pkgs.callPackage ../. {};
|
||||||
|
|
||||||
inherit (lib) mkOption;
|
inherit (lib) mkOption;
|
||||||
inherit (lib.types) anything submodule;
|
inherit (lib.types) submodule;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.shb.contracts.backup = mkOption {
|
options.shb.contracts.backup = mkOption {
|
||||||
|
|
@ -23,24 +23,7 @@ in
|
||||||
'';
|
'';
|
||||||
|
|
||||||
type = submodule {
|
type = submodule {
|
||||||
options = {
|
options = contracts.backup.contract;
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ in
|
||||||
inherit mkContractFunctions;
|
inherit mkContractFunctions;
|
||||||
|
|
||||||
databasebackup = import ./databasebackup.nix { inherit lib; };
|
databasebackup = import ./databasebackup.nix { inherit lib; };
|
||||||
backup = import ./backup.nix { inherit lib; };
|
backup = importContract ./backup.nix;
|
||||||
mount = import ./mount.nix { inherit lib; };
|
mount = import ./mount.nix { inherit lib; };
|
||||||
secret = importContract ./secret.nix;
|
secret = importContract ./secret.nix;
|
||||||
ssl = import ./ssl.nix { inherit lib; };
|
ssl = import ./ssl.nix { inherit lib; };
|
||||||
|
|
|
||||||
|
|
@ -316,29 +316,17 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
user = name;
|
user = name;
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
cfg.${name}.dataDir
|
cfg.${name}.dataDir
|
||||||
];
|
];
|
||||||
excludePatterns = [".db-shm" ".db-wal" ".mono"];
|
excludePatterns = [".db-shm" ".db-wal" ".mono"];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} // (c.moreOptions or {});
|
} // (c.moreOptions or {});
|
||||||
|
|
|
||||||
|
|
@ -88,28 +88,16 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
user = "audiobookshelf";
|
user = "audiobookshelf";
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
"/var/lib/audiobookshelf"
|
"/var/lib/audiobookshelf"
|
||||||
];
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,28 +244,16 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
user = "deluge";
|
user = "deluge";
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
cfg.dataDir
|
cfg.dataDir
|
||||||
];
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -241,30 +241,18 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = mkOption {
|
backup = mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
user = options.services.forgejo.user.value;
|
user = options.services.forgejo.user.value;
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
options.services.forgejo.dump.backupDir.value
|
options.services.forgejo.dump.backupDir.value
|
||||||
] ++ optionals (cfg.repositoryRoot != null) [
|
] ++ optionals (cfg.repositoryRoot != null) [
|
||||||
cfg.repositoryRoot
|
cfg.repositoryRoot
|
||||||
];
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,28 +63,17 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = {
|
type = lib.types.submodule {
|
||||||
user = "grocy";
|
options = contracts.backup.mkRequester {
|
||||||
sourceDirectories = [
|
user = "grocy";
|
||||||
cfg.dataDir
|
sourceDirectories = [
|
||||||
];
|
cfg.dataDir
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,28 +55,16 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
user = "hledger";
|
user = "hledger";
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
cfg.dataDir
|
cfg.dataDir
|
||||||
];
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -140,29 +140,17 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
user = "hass";
|
user = "hass";
|
||||||
# No need for backup hooks as we use an hourly automation job in home assistant directly with a cron job.
|
# No need for backup hooks as we use an hourly automation job in home assistant directly with a cron job.
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
"/var/lib/hass/backups"
|
"/var/lib/hass/backups"
|
||||||
];
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -151,28 +151,16 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
user = "jellyfin";
|
user = "jellyfin";
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
"/var/lib/jellyfin"
|
"/var/lib/jellyfin"
|
||||||
];
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -519,29 +519,17 @@ in
|
||||||
|
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
user = "nextcloud";
|
user = "nextcloud";
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
cfg.dataDir
|
cfg.dataDir
|
||||||
];
|
];
|
||||||
excludePatterns = [".rnd"];
|
excludePatterns = [".rnd"];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,28 +128,16 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
backup = lib.mkOption {
|
backup = lib.mkOption {
|
||||||
type = contracts.backup.request;
|
|
||||||
description = ''
|
description = ''
|
||||||
Backup configuration. This is an output option.
|
Backup configuration.
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
```
|
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
type = lib.types.submodule {
|
||||||
default = {
|
options = contracts.backup.mkRequester {
|
||||||
user = "vaultwarden";
|
user = "vaultwarden";
|
||||||
sourceDirectories = [
|
sourceDirectories = [
|
||||||
dataFolder
|
dataFolder
|
||||||
];
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -162,6 +150,10 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
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 = {
|
services.vaultwarden = {
|
||||||
enable = true;
|
enable = true;
|
||||||
dbBackend = "postgresql";
|
dbBackend = "postgresql";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ pkgs, lib, ... }:
|
{ pkgs, ... }:
|
||||||
let
|
let
|
||||||
pkgs' = pkgs;
|
pkgs' = pkgs;
|
||||||
in
|
in
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ let
|
||||||
../../modules/blocks/restic.nix
|
../../modules/blocks/restic.nix
|
||||||
];
|
];
|
||||||
shb.restic.instances."testinstance" = {
|
shb.restic.instances."testinstance" = {
|
||||||
request = config.shb.vaultwarden.backup;
|
request = config.shb.vaultwarden.backup.request;
|
||||||
settings = {
|
settings = {
|
||||||
enable = true;
|
enable = true;
|
||||||
passphrase.result = config.shb.hardcodedsecret.backupPassphrase.result;
|
passphrase.result = config.shb.hardcodedsecret.backupPassphrase.result;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue