nix-config/modules/nixos-modules/storage/zfs.nix

153 lines
4.7 KiB
Nix

args @ {
lib,
pkgs,
config,
...
}: let
datasetSubmodule = (import ./submodules/dataset.nix) args;
in {
options.storage = {
zfs = {
enable = lib.mkEnableOption "Should zfs be enabled on this system.";
notifications = {
enable = lib.mkEnableOption "are notifications enabled";
host = lib.mkOption {
type = lib.types.str;
description = "what is the host that we are going to send the email to";
};
port = lib.mkOption {
type = lib.types.port;
description = "what port is the host using to receive mail on";
};
to = lib.mkOption {
type = lib.types.str;
description = "what account is the email going to be sent to";
};
user = lib.mkOption {
type = lib.types.str;
description = "what user is the email going to be set from";
};
tokenFile = lib.mkOption {
type = lib.types.str;
description = "file containing the password to be used by msmtp for notifications";
};
};
pool = let
deviceType =
lib.types.coercedTo lib.types.str (device: {
device = device;
boot = false;
}) {
device = lib.mkOption {
type = lib.types.str;
};
boot = lib.mkEnableOption "should this device be a boot device";
};
in {
encryption = {
enable = lib.mkEnableOption "Should encryption be enabled on this pool.";
keyformat = lib.mkOption {
type = lib.types.enum ["raw" "hex" "passphrase"];
default = "hex";
description = "Format of the encryption key";
};
keylocation = lib.mkOption {
type = lib.types.str;
default = "prompt";
description = "Location of the encryption key";
};
};
mode = lib.mkOption {
type = lib.types.enum ["stripe" "mirror" "raidz1" "raidz2" "raidz3"];
default = "raidz2";
description = "ZFS redundancy mode for the pool";
};
bootPartitionSize = lib.mkOption {
type = lib.types.str;
default = "2G";
description = "Size of the boot partition on boot drives";
};
vdevs = lib.mkOption {
type = lib.types.listOf (lib.types.listOf deviceType);
default = [];
description = "List of vdevs, where each vdev is a list of devices";
};
cache = lib.mkOption {
type = lib.types.attrsOf deviceType;
default = {};
};
};
rootDataset = lib.mkOption {
type = lib.types.submodule datasetSubmodule;
description = "Root ZFS dataset to create";
default = {};
};
datasets = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule datasetSubmodule);
description = "Additional ZFS datasets to create";
default = {};
};
};
};
config = lib.mkIf config.storage.zfs.enable (lib.mkMerge [
{
services.zfs = {
autoScrub.enable = true;
autoSnapshot.enable = true;
};
# TODO: configure disko
# TODO: assertion that we have a boot device
# TODO: check that disks on system match configuration and warn user if they don't
# TODO: check that datasets on system match configuration and warn user if they don't
}
(lib.mkIf config.storage.zfs.notifications.enable {
programs.msmtp = {
enable = true;
setSendmail = true;
defaults = {
aliases = "/etc/aliases";
port = config.storage.zfs.notifications.port;
tls_trust_file = "/etc/ssl/certs/ca-certificates.crt";
tls = "on";
auth = "login";
tls_starttls = "off";
};
accounts = {
zfs_notifications = {
auth = true;
tls = true;
host = config.storage.zfs.notifications.host;
passwordeval = "cat ${config.storage.zfs.notifications.tokenFile}";
user = config.storage.zfs.notifications.user;
from = config.storage.zfs.notifications.user;
};
};
};
services.zfs = {
zed = {
enableMail = true;
settings = {
ZED_DEBUG_LOG = "/tmp/zed.debug.log";
ZED_EMAIL_ADDR = [config.storage.zfs.notifications.to];
ZED_EMAIL_PROG = "${pkgs.msmtp}/bin/msmtp";
ZED_EMAIL_OPTS = "-a zfs_notifications @ADDRESS@";
ZED_NOTIFY_INTERVAL_SECS = 3600;
ZED_NOTIFY_VERBOSE = true;
ZED_USE_ENCLOSURE_LEDS = true;
ZED_SCRUB_AFTER_RESILVER = true;
};
};
};
})
]);
}