storage-refactor #9
7 changed files with 160 additions and 140 deletions
|
|
@ -16,6 +16,7 @@
|
||||||
./tailscale.nix
|
./tailscale.nix
|
||||||
./steam.nix
|
./steam.nix
|
||||||
./server
|
./server
|
||||||
|
./storage
|
||||||
];
|
];
|
||||||
|
|
||||||
nixpkgs.config.permittedInsecurePackages = [
|
nixpkgs.config.permittedInsecurePackages = [
|
||||||
|
|
|
||||||
|
|
@ -3,146 +3,6 @@
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: {
|
}: {
|
||||||
options.storage = let
|
|
||||||
datasetSubmodule = {name, ...}: {
|
|
||||||
# TODO: we need to figure out what options a dataset can have in zfs
|
|
||||||
};
|
|
||||||
|
|
||||||
impermanenceDatasetSubmodules = [
|
|
||||||
datasetSubmodule
|
|
||||||
({...}: let
|
|
||||||
pathPermissions = {
|
|
||||||
read = lib.mkEnableOption "should the path have read permissions";
|
|
||||||
write = lib.mkEnableOption "should the path have read permissions";
|
|
||||||
execute = lib.mkEnableOption "should the path have read permissions";
|
|
||||||
};
|
|
||||||
pathTypeSubmodule = {name, ...}: {
|
|
||||||
options = {
|
|
||||||
enable = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
owner = {
|
|
||||||
user = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "nouser";
|
|
||||||
};
|
|
||||||
permissions = pathPermissions;
|
|
||||||
};
|
|
||||||
group = {
|
|
||||||
group = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "nogroup";
|
|
||||||
};
|
|
||||||
permissions = pathPermissions;
|
|
||||||
};
|
|
||||||
other = {
|
|
||||||
permissions = pathPermissions;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
options = {
|
|
||||||
files = lib.types.mkOption {
|
|
||||||
type = lib.types.attrsOf (lib.types.submodule pathTypeSubmodule);
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
directories = {
|
|
||||||
type = lib.types.attrsOf (lib.types.submodule pathTypeSubmodule);
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
];
|
|
||||||
in {
|
|
||||||
zfs = {
|
|
||||||
# TODO: enable option implementation
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# TODO: we need options to configure zfs pools
|
|
||||||
# we should have warnings when the configured pool is missing drives after activation
|
|
||||||
# TODO: implementation of this
|
|
||||||
# TODO: validations that we have at least one boot drive
|
|
||||||
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 = lib.mkEnableOption "Should encryption be enabled on this pool.";
|
|
||||||
vdevs = lib.mkOption {
|
|
||||||
type = lib.types.listOf deviceType;
|
|
||||||
default = [];
|
|
||||||
};
|
|
||||||
cache = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf deviceType;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# TODO:create the root dataset automatically
|
|
||||||
# TODO: dataset option that is a submodule that adds datasets to the system
|
|
||||||
# warnings for when a dataset was created in the past on a system but it is now missing some of the options defined for it
|
|
||||||
datasets = lib.types.attrsOf (lib.types.submodule datasetSubmodule);
|
|
||||||
};
|
|
||||||
|
|
||||||
impermanence = {
|
|
||||||
enable = lib.mkEnableOption "should impermanence be enabled for this system";
|
|
||||||
# TODO: enable option implementation
|
|
||||||
|
|
||||||
# TODO: assertion that zfs needs to be enabled when impermanence is enabled
|
|
||||||
|
|
||||||
# TODO: datasets option that is a submodule that will be used to define what datasets to add to the storage system
|
|
||||||
# We should by default create the `local`, `local/system/nix`, `local/system/root`, `persist` `persist/system/root`, and `persist/system/var/log` datasets
|
|
||||||
# We should also create datasets for systemd modules that have have impermanence enabled for them
|
|
||||||
|
|
||||||
datasets = lib.types.attrsOf (lib.types.submodule impermanenceDatasetSubmodules);
|
|
||||||
|
|
||||||
# TODO: this should just live under home-manager.users.<user>.storage.impermanence
|
|
||||||
home-manager = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
|
||||||
enable = lib.mkEnableOption "should impermanence be enabled for this user";
|
|
||||||
|
|
||||||
# We should by default create the `local/home/${name}`, and `persist/home/${name}` datasets
|
|
||||||
datasets = lib.types.attrsOf (lib.types.submodule impermanenceDatasetSubmodules);
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
# TODO: we should have an impermanence module for home manager that proxies its values namespaced to the user down here that matches the same interface
|
|
||||||
|
|
||||||
# TODO: we should have a way of enabling impermanence for a systemd config
|
|
||||||
# these should have an option to put their folder into their own dataset (this needs to support private vs non private)
|
|
||||||
# options for features that can be added to the dataset
|
|
||||||
};
|
|
||||||
|
|
||||||
options.host.impermanence.enable = lib.mkEnableOption "are we going to use impermanence on this device";
|
options.host.impermanence.enable = lib.mkEnableOption "are we going to use impermanence on this device";
|
||||||
|
|
||||||
config = lib.mkMerge [
|
config = lib.mkMerge [
|
||||||
|
|
|
||||||
12
modules/nixos-modules/storage/default.nix
Normal file
12
modules/nixos-modules/storage/default.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{...}: {
|
||||||
|
# TODO: we should have an impermanence module for home manager that proxies its values namespaced to the user down here that matches the same interface
|
||||||
|
|
||||||
|
# TODO: we should have a way of enabling impermanence for a systemd config
|
||||||
|
# these should have an option to put their folder into their own dataset (this needs to support private vs non private)
|
||||||
|
# options for features that can be added to the dataset
|
||||||
|
|
||||||
|
imports = [
|
||||||
|
./impermanence.nix
|
||||||
|
./zfs.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
31
modules/nixos-modules/storage/impermanence.nix
Normal file
31
modules/nixos-modules/storage/impermanence.nix
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
args @ {lib, ...}: let
|
||||||
|
impermanenceDatasetSubmodules = (import ./submodules/impermanenceDataset.nix) args;
|
||||||
|
in {
|
||||||
|
options.storage = {
|
||||||
|
impermanence = {
|
||||||
|
enable = lib.mkEnableOption "should impermanence be enabled for this system";
|
||||||
|
# TODO: enable option implementation
|
||||||
|
|
||||||
|
# TODO: assertion that zfs needs to be enabled when impermanence is enabled
|
||||||
|
|
||||||
|
# TODO: datasets option that is a submodule that will be used to define what datasets to add to the storage system
|
||||||
|
# We should by default create the `local`, `local/system/nix`, `local/system/root`, `persist` `persist/system/root`, and `persist/system/var/log` datasets
|
||||||
|
# We should also create datasets for systemd modules that have have impermanence enabled for them
|
||||||
|
|
||||||
|
datasets = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule impermanenceDatasetSubmodules);
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO: this should just live under home-manager.users.<user>.storage.impermanence
|
||||||
|
home-manager = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
||||||
|
enable = lib.mkEnableOption "should impermanence be enabled for this user";
|
||||||
|
# We should by default create the `local/home/${name}`, and `persist/home/${name}` datasets
|
||||||
|
datasets = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule impermanenceDatasetSubmodules);
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
3
modules/nixos-modules/storage/submodules/dataset.nix
Normal file
3
modules/nixos-modules/storage/submodules/dataset.nix
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{name, ...}: {
|
||||||
|
# TODO: we need to figure out what options a dataset can have in zfs
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
{lib, ...}: let
|
||||||
|
pathPermissions = {
|
||||||
|
read = lib.mkEnableOption "should the path have read permissions";
|
||||||
|
write = lib.mkEnableOption "should the path have read permissions";
|
||||||
|
execute = lib.mkEnableOption "should the path have read permissions";
|
||||||
|
};
|
||||||
|
pathTypeSubmodule = {name, ...}: {
|
||||||
|
options = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
owner = {
|
||||||
|
user = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "nouser";
|
||||||
|
};
|
||||||
|
permissions = pathPermissions;
|
||||||
|
};
|
||||||
|
group = {
|
||||||
|
group = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "nogroup";
|
||||||
|
};
|
||||||
|
permissions = pathPermissions;
|
||||||
|
};
|
||||||
|
other = {
|
||||||
|
permissions = pathPermissions;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
imports = [
|
||||||
|
./dataset.nix
|
||||||
|
];
|
||||||
|
options = {
|
||||||
|
files = lib.types.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule pathTypeSubmodule);
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
directories = {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule pathTypeSubmodule);
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
67
modules/nixos-modules/storage/zfs.nix
Normal file
67
modules/nixos-modules/storage/zfs.nix
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
args @ {lib, ...}: let
|
||||||
|
datasetSubmodule = (import ./submodules/dataset.nix) args;
|
||||||
|
in {
|
||||||
|
options.storage = {
|
||||||
|
zfs = {
|
||||||
|
# TODO: enable option implementation
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO: we need options to configure zfs pools
|
||||||
|
# we should have warnings when the configured pool is missing drives after activation
|
||||||
|
# TODO: implementation of this
|
||||||
|
# TODO: validations that we have at least one boot drive
|
||||||
|
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 = lib.mkEnableOption "Should encryption be enabled on this pool.";
|
||||||
|
vdevs = lib.mkOption {
|
||||||
|
type = lib.types.listOf deviceType;
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
cache = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf deviceType;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO:create the root dataset automatically
|
||||||
|
# TODO: dataset option that is a submodule that adds datasets to the system
|
||||||
|
# warnings for when a dataset was created in the past on a system but it is now missing some of the options defined for it
|
||||||
|
datasets = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule datasetSubmodule);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue