129 lines
4 KiB
Nix
129 lines
4 KiB
Nix
{
|
|
config,
|
|
pkgs,
|
|
lib,
|
|
...
|
|
}:
|
|
|
|
let
|
|
cfg = config.shb.zfs;
|
|
in
|
|
{
|
|
options.shb.zfs = {
|
|
defaultPoolName = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "ZFS pool name datasets should be created on if no pool name is given in the dataset.";
|
|
};
|
|
|
|
datasets = lib.mkOption {
|
|
description = ''
|
|
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
|
|
'';
|
|
default = { };
|
|
example = lib.literalExpression ''
|
|
shb.zfs."safe/postgresql".path = "/var/lib/postgresql";
|
|
'';
|
|
type = lib.types.attrsOf (
|
|
lib.types.submodule {
|
|
options = {
|
|
enable = lib.mkEnableOption "shb.zfs.datasets";
|
|
|
|
poolName = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "ZFS pool name this dataset should be created on. Overrides the defaultPoolName.";
|
|
};
|
|
|
|
path = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = "Path this dataset should be mounted on. If the string 'none' is given, the dataset will not be mounted.";
|
|
};
|
|
|
|
mode = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
description = "If non null, unix mode to apply to the dataset root folder.";
|
|
default = null;
|
|
example = "ug=rwx,g+s";
|
|
};
|
|
|
|
owner = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
description = "If non null, unix user to apply to the dataset root folder.";
|
|
default = null;
|
|
example = "syncthing";
|
|
};
|
|
|
|
group = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
description = "If non null, unix group to apply to the dataset root folder.";
|
|
default = null;
|
|
example = "syncthing";
|
|
};
|
|
|
|
defaultACLs = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
description = ''
|
|
If non null, default ACL to set on the dataset root folder.
|
|
|
|
Executes "setfacl -d -m $acl $path"
|
|
'';
|
|
default = null;
|
|
example = "g:syncthing:rwX";
|
|
};
|
|
};
|
|
}
|
|
);
|
|
};
|
|
};
|
|
|
|
config = {
|
|
assertions = [
|
|
{
|
|
assertion =
|
|
lib.any (x: x.poolName == null) (lib.mapAttrsToList (n: v: v) cfg.datasets)
|
|
-> cfg.defaultPoolName != null;
|
|
message = "Cannot have both datasets.poolName and defaultPoolName set to null";
|
|
}
|
|
];
|
|
|
|
system.activationScripts = lib.mapAttrs' (
|
|
name: cfg':
|
|
let
|
|
dataset = (if cfg'.poolName != null then cfg'.poolName else cfg.defaultPoolName) + "/" + name;
|
|
in
|
|
lib.attrsets.nameValuePair "zfsCreate-${name}" {
|
|
text = ''
|
|
${pkgs.zfs}/bin/zfs list ${dataset} > /dev/null 2>&1 \
|
|
|| ${pkgs.zfs}/bin/zfs create \
|
|
-o mountpoint=none \
|
|
${dataset} || :
|
|
|
|
[ "$(${pkgs.zfs}/bin/zfs get -H mountpoint -o value ${dataset})" = ${cfg'.path} ] \
|
|
|| ${pkgs.zfs}/bin/zfs set \
|
|
mountpoint="${cfg'.path}" \
|
|
${dataset}
|
|
|
|
''
|
|
+ lib.optionalString (cfg'.path != "none" && cfg'.mode != null) ''
|
|
chmod "${cfg'.mode}" "${cfg'.path}"
|
|
''
|
|
+ lib.optionalString (cfg'.path != "none" && cfg'.owner != null) ''
|
|
chown "${cfg'.owner}" "${cfg'.path}"
|
|
''
|
|
+ lib.optionalString (cfg'.path != "none" && cfg'.group != null) ''
|
|
chown :"${cfg'.group}" "${cfg'.path}"
|
|
''
|
|
+ lib.optionalString (cfg'.path != "none" && cfg'.defaultACLs != null) ''
|
|
${pkgs.acl}/bin/setfacl -d -m "${cfg'.defaultACLs}" "${cfg'.path}"
|
|
'';
|
|
}
|
|
) cfg.datasets;
|
|
};
|
|
}
|