Created
January 12, 2024 17:13
-
-
Save mweinelt/608a5b7d29a9f6c41d4ff71cc472c214 to your computer and use it in GitHub Desktop.
Bupstash NixOS module mock-up
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ config | |
, lib | |
, pkgs | |
, ... | |
}: | |
let | |
inherit (lib) | |
concatMapStringsSep | |
escapeShellArgs | |
mapAttrs' | |
mdDoc | |
mkIf | |
mkOption | |
mkPackageOptionMD | |
nullOr | |
nameValuePair | |
optionalAttrs | |
optionalString | |
types | |
; | |
cfg = config.service.bupstash; | |
in { | |
options.services.bupstash = let | |
putJob = with types; { | |
enable = mkOption { | |
type = bool; | |
default = true; | |
example = false; | |
description = '' | |
Whether to enable this backup job | |
''; | |
}; | |
user = mkOption { | |
type = nullOr str; | |
default = null; | |
example = "postgres"; | |
description = mdDoc '' | |
User to run this put job as. Defaults to `null`, which uses a dynamic user | |
named `bupstash`, which has permissions to read all files through `CAP_DAC_READ_OVERRIDE`. | |
''; | |
}; | |
repository = mkOption { | |
type = nullOr str; | |
example = "ssh://offsite.example.com/machine.example.com"; | |
description = mdDoc '' | |
The repository to backup the paths into. Available as `BUPSTASH_REPOSITORY`. | |
''; | |
}; | |
repositoryCommand = mkOption { | |
type = nullOr str; | |
example = "ssh -l backup -i /run/keys/bupstash/id_bupstash offsite.example.com"; | |
description = mdDoc '' | |
The command to run to connect to an instance of `bupstash-serve`. Available as | |
`BUPSTASH_REPOSITORY_COMMAND`. | |
''; | |
}; | |
key = mkOption { | |
type = nullOr str; | |
description = mdDoc '' | |
Encryption key that is allowed to put to the repository. Available as `BUPSTASH_KEY`. | |
Relevant documentation: | |
- [Secure offline keys](https://bupstash.io/doc/guides/Secure%20Offline%20Keys.html) | |
''; | |
}; | |
keyCommand = mkOption { | |
type = nullOr str; | |
example = "cat /run/keys/bupstash/put.key"; | |
description = mdDoc '' | |
Command to retrieve the encryption key, that is allowed to put to the repository. | |
Available as `BUPSTASH_KEY_COMMAND`. | |
Relevant documentation: | |
- [Secure offline keys](https://bupstash.io/doc/guides/Secure%20Offline%20Keys.html) | |
''; | |
}; | |
tags = mkOption { | |
type = attrsOf str; | |
default = { }; | |
example = literalExample '' | |
{ | |
name = "example.zip" | |
} | |
''; | |
description = '' | |
Key/value pairs attached to the data stored through the put call. | |
''; | |
}; | |
paths = mkOption { | |
type = nullOr (listOf path); | |
default = null; | |
example = [ | |
"/home/" | |
"/var/backup" | |
"/var/lib" | |
]; | |
description = '' | |
List of files or directories to save. | |
''; | |
}; | |
exec = mkOtion { | |
type = nullOr str; | |
default = null; | |
example = literalExample '' | |
''${config.services.postgresql.package}/bin/pg_dump | |
''; | |
}; | |
extraArgs = mkOption { | |
type = listOf str; | |
default = []; | |
description = '' | |
List of parameters and arguments to append to the `bupstash put` command. | |
''; | |
}; | |
preHook = mkOption { | |
type = nullOr lines; | |
default = null; | |
example = literalExpression ''\ | |
# https://openzfs.github.io/openzfs-docs/man/8/zfs-snapshot.8.html | |
''${config.boot.zfs.package}/bin/zfs snapshot -r pool/state@backup | |
''; | |
description = '' | |
Commands that are run before the put job is run. Executed with root permissions. | |
Useful to create snapshots or modify the environment variables consumed by bupstash. | |
''; | |
}; | |
postHook = mkOption { | |
type = nullOr lines; | |
default = null; | |
example = literalExpression '' | |
# https://openzfs.github.io/openzfs-docs/man/8/zfs-snapshot.8.html | |
''${config.boot.zfs.package}/bin/zfs destroy -r pool/state@backup | |
''; | |
description = '' | |
Commands that are run before the put job is run. | |
Useful to remove snapshots or modify the environment variables consumed by bupstash. | |
''; | |
}; | |
}; | |
in with types; { | |
package = mkPackageOptionMD pkgs "bupstash" { }; | |
putJobs = mkOption { | |
description = mdDoc '' | |
List of bupstash put jobs. | |
Relevant documentation: | |
- [bupstash-put](https://bupstash.io/doc/man/bupstash-put.html) | |
''; | |
default = { }; | |
type = attrsOf putJob; | |
}; | |
}; | |
config = let | |
mkPutService = name: job: nameValuePair "bupstash-put-${name}" { | |
description = "Bupstash Put Job"; | |
documentation = [ | |
"man:bupstash-put(1)" | |
"https://bupstash.io/doc/man/bupstash-put.html" | |
]; | |
environment = { | |
BUPSTASH_REPOSITORY = job.repository; | |
BUPSTASH_KEY = job.key; | |
}; | |
serviceConfig = { | |
ExecStart = '' | |
${lib.getExe cfg.package} put \ | |
${optionalString job.exec != null "--exec ${escapeShellArgs job.exec}"} \ | |
${concatMapStringsSep (k: v: "${k}=${v}\n") job.tags} | |
${optionalString job.paths != null (escapeShellArgs job.paths)} \ | |
${concatMapStringsSep " " escapeShellArgs job.extraArgs} | |
''; | |
ExecStartPre = mkIf (job.preHook != null) | |
("+" + pkgs.writeShellScript "bupstash-put-${job.name}-prehook" job.preHook); | |
ExecStopPost = mkIf (job.postHook != null) | |
("+" + pkgs.writeShellScript "bupstash-put-${job.name}-posthook" job.postHook); | |
} // optionalAttrs (job.user == null) { | |
DynamicUser = true; | |
User = "bupstash"; | |
AmbientCapabilities = [ | |
"CAP_DAC_READ_OVERRIDE" | |
]; | |
Capabilities = [ | |
"CAP_DAC_READ_OVERRIDE" | |
]; | |
} // optionalAttrs (job.user != null) { | |
User = job.user; | |
}; | |
}; | |
in mkIf (cfg.jobs != []) { | |
systemd.services = mapAttrs' mkPutService cfg.jobs; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment