ZFS Block
Defined in /modules/blocks/zfs.nix:
{
inputs,
...
}:
{
imports = [
inputs.selfhostblocks.nixosModules.zfs
];
}
This block creates ZFS datasets, optionally mounts them and sets permissions on the mount point. It also enables taking snapshots on activation.
Features
Creates ZFS dataset which is optionally mounted.
Backup of the files in the dataset
shb.zfs.<name>.backupthrough the backup contract.Backup of the dataset itself
shb.zfs.<name>.datasetbackupthrough the dataset backup contract.Take a snapshot before activating or deploying allowing a safe rollback.
Usage
Create a dataset at root/safe/users mounted on /var/lib/nixos:
shb.zfs.pools.root.datasets."safe/users".path = "/var/lib/nixos";
Create a dataset at backup/syncoid but do not mount it:
shb.zfs.pools.backup.datasets."syncoid".path = "none";
Create a dataset at root/syncthing and set custom permissions and ACL.
Permission and ACL are only enforced for the mount point.
shb.zfs.pools.root.datasets."syncthing" = {
path = "/srv/syncthing";
mode = "ug=rwx,g+s,o=";
owner = "syncthing";
group = "syncthing";
defaultACLs = "g:syncthing:rwX";
};
Backup dataset
To backup the dataset directly, use the dataset backup contract. For example, with the sanoid module as the dataset backup contract provider:
{
shb.zfs.pools.root.datasets.home = {
path = "/home";
};
shb.sanoid.backup."root/home" = {
request = shb.zfs.pools.root.datasets.home.datasetBackup.request;
template = "yearly";
};
}
See the Sanoid block for more examples.
Backup files
To backup the files in the dataset, use the file backup contract. For example, with the restic module as the file backup contract provider:
{
shb.zfs.pools.root.datasets.home = {
path = "/home";
};
shb.restic.instances."myservice" = {
request = shb.zfs.pools.root.datasets.home.backup.request;
};
}
See the Restic block for more examples.
Snapshot before activation
To take a snapshot of all datasets before activating a new configuration:
{
shb.zfs.snapshotBeforeActivation.enable = true;
}
This does not take a recursive snapshot by default, to do it recursively, do:
{
shb.zfs.snapshotBeforeActivation = {
enable = true;
recursive = true;
};
}
We did not specify datasets manually, which means the datasets list comes from boot.zfs.extraPools.
To specify the datasets manually, you can use:
{
shb.zfs.snapshotBeforeActivation = {
enable = true;
datasets = [ "root" "root/var" ];
};
}
Options Reference
-
shb.zfs.pools -
Attrset of ZFS pools under which datasets will be created.
The ZFS pools are not managed by this module, they should already exist.
Each pool named here will be added to the
boot.zfs.extraPoolsoption.Type: attribute set of (submodule)
Default:
{ }Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets -
ZFS Datasets.
Each entry in the attrset will be created and mounted in the given path. The attrset name is the dataset name.
This block implements the following contracts:
mount
Type: attribute set of (submodule)
Default:
{ }Example:
shb.zfs."safe/postgresql".path = "/var/lib/postgresql";Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.after -
Order creating this dataset after the mentioned ones. This only works with datasets managed by this module.
Use the name of the dataset without the pool name.
Type: list of string
Default:
[ ]Example:
[ "backup" ]Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup -
Backup contract consumer configuration.
This contract will backup the files inside the dataset.
Type: submodule
Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.request -
Request part of the backup contract.
Options set by the requester module enforcing how to backup files.
Type: submodule
Default: { user = root; sourceDirectories = [ shb.zfs.pools.<name>.datasets.<name>.path ] ; excludePatterns = [ ]; hooks.beforeBackup = [ ]; hooks.afterBackup = [ ]; };
Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.request.excludePatterns -
File patterns to exclude.
Type: list of string
Default:
[ ]Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.request.hooks -
Hooks to run around the backup.
Type: submodule
Default:
{ }Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.request.hooks.afterBackup -
Hooks to run after backup.
Type: list of string
Default:
[ ]Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.request.hooks.beforeBackup -
Hooks to run before backup.
Type: list of string
Default:
[ ]Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.request.sourceDirectories -
Directories to backup.
Type: non-empty (list of string)
Default: [ shb.zfs.pools.<name>.datasets.<name>.path ]
Example:
"/var/lib/vaultwarden"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.request.user -
Unix user doing the backups.
Type: string
Default:
"root"Example:
"vaultwarden"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.result -
Result part of the backup contract.
Options set by the provider module that indicates the name of the backup and restore scripts.
Type: submodule
Default:
""Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.result.backupService -
Name of service backing up the database.
This script can be ran manually to backup the database:
$ systemctl start backup.serviceType: string
Default:
"backup.service"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.backup.result.restoreScript -
Name of script that can restore the database. One can then list snapshots with:
$ restore snapshots <snapshot 1> <metadata> <snapshot 2> <metadata>And restore the database with:
$ restore restore <snapshot 1>Type: string
Default:
"restore"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.datasetbackup -
ZFS dataset backup contract configuration.
This contract will take snaphots of the dataset.
Type: submodule
Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.datasetbackup.request -
Request part of the backup contract.
Options set by the requester module enforcing how to backup files.
Type: submodule
Default:
{ }Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.datasetbackup.request.dataset -
Dataset to backup, including the pool name.
Type: string
Default:
"‹name›"Example:
"root/home"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.datasetbackup.result -
Result part of the backup contract.
Options set by the provider module that indicates the name of the backup and restore scripts.
Type: submodule
Default:
{ }Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.datasetbackup.result.backupService -
Name of service backing up the database.
This script can be ran manually to backup the database:
$ systemctl start backup.serviceType: string
Default:
"backup.service"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.datasetbackup.result.restoreScript -
Name of script that can restore the database. One can then list snapshots with:
$ restore snapshots <snapshot 1> <metadata> <snapshot 2> <metadata>And restore the database with:
$ restore restore <snapshot 1>It is not garanteed to be able to restore back to a snapshot in the future. With the above example, it may not be possible to restore
<snapshot 2>after having restored<snapshot 1>.Type: string
Default:
"restore"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.defaultACLs -
If non null, default ACL to set on the dataset root folder.
Executes “setfacl -d -m $acl $path”
Type: null or string
Default:
nullExample:
"g:syncthing:rwX"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.group -
If non null, unix group to apply to the dataset root folder.
Type: null or string
Default:
nullExample:
"syncthing"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.mode -
If non null, unix mode to apply to the dataset root folder.
Type: null or string
Default:
nullExample:
"ug=rwx,g+s"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.owner -
If non null, unix user to apply to the dataset root folder.
Type: null or string
Default:
nullExample:
"syncthing"Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.pools.<name>.datasets.<name>.path -
Path this dataset should be mounted on. If the string ‘none’ is given, the dataset will not be mounted.
Type: string
Declared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.snapshotBeforeActivation.enable -
Take a snapshot of all datasets before activation
Type: boolean
Default:
falseDeclared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.snapshotBeforeActivation.datasets -
Defines all datasets to take a snapshot of.
If set to
null, the default, take the list of datasets fromconfig.boot.zfs.extraPools.The snapshots are not recursive unless specificed in the
recursiveoption.Type: null or (list of string)
Default:
nullDeclared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.snapshotBeforeActivation.recursive -
If true, take snapshots recurisevly on the given datasets.
Type: boolean
Default:
falseDeclared by:
<selfhostblocks/modules/blocks/zfs.nix> -
shb.zfs.snapshotBeforeActivation.template -
Bash command to generate the snapshot name. $1 is the path to the new generation.
Type: string
Default:
"pre-$(date --utc '+%y%m%dT%H%M%S')-$(basename \"$1\")"Declared by:
<selfhostblocks/modules/blocks/zfs.nix>