Skip to content

Commit

Permalink
feat(modules/mcl-disko): Create ZFS configuration module
Browse files Browse the repository at this point in the history
  • Loading branch information
galin-s committed Jan 23, 2025
1 parent c3d851e commit 6b33832
Show file tree
Hide file tree
Showing 5 changed files with 348 additions and 0 deletions.
1 change: 1 addition & 0 deletions modules/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
./pyroscope
./folder-size-metrics
./shard-split
./mcl-disko
];
}
162 changes: 162 additions & 0 deletions modules/mcl-disko/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
{ withSystem, inputs, ... }:
{
flake.modules.nixos.mcl-disko =
{
pkgs,
config,
lib,
...
}:
with lib;
let
cfg = config.mcl.disko;
in
{
imports = [
inputs.disko.nixosModules.disko
];
options.mcl.disko = {
enable = mkEnableOption "Enable Module";

legacyBoot = mkOption {
type = types.bool;
default = false;
example = true;
description = "Declare if the configuration is for a Hetzner server or not";
};

swapSize = mkOption {
type = types.str;
default = "32G";
example = "32768M";
description = "The size of the hard disk space used when RAM is full";
};

espSize = mkOption {
type = types.str;
default = "4G";
example = "4096M";
description = "The size of the hard disk space used for the ESP filesystem";
};

disks = mkOption {
type = types.listOf types.str;
default = [ ];
example = [
"/dev/disk/sda"
"/dev/disk/sdb"
"/dev/disk/sdc"
];
description = "The disk partitions to be used when ZFS is being created";
};

zpool = {
name = mkOption {
type = types.str;
default = "zfs_root";
description = "The name of the ZFS Pool";
};

mode = mkOption {
type = types.enum [
"stripe"
"mirror"
"raidz1"
"raidz2"
"raidz3"
];
default = "stripe";
description = "Set ZFS Pool redundancy - e.g. 'mirror', 'raidz1', etc.";
};

extraDatasets = mkOption {
type = types.attrsOf (
types.submodule (
{ name, ... }:
{
options = {
mountpoint = mkOption {
type = types.nullOr types.str;
default = name;
example = "/var/lib";
description = "The ZFS dataset mountpoint";
};

type = mkOption {
type = types.enum [
"zfs_fs"
"zfs_volume"
];
default = "zfs_fs";
description = "Type of ZFS dataset";
};
snapshot = mkEnableOption "Whether to enable ZFS snapshots";
};

}
)
);
default = { };
example = {
"/opt".snapshot = false;
"/opt/downloads".snapshot = false;
"/opt/downloads/vm-images" = {
snapshot = false;
options = {
quota = "120G";
};
};
};
description = "Extra ZFS Pool datasets";
};
};
};

config.disko =
let
makePrimaryZfsDisk = import ./primaryZfsPartition.nix;
makeSecondaryZfsDisk = import ./secondaryZfsPartition.nix;

first = builtins.head cfg.disks;
rest = builtins.tail cfg.disks;
secondaryDisks = builtins.listToAttrs (
builtins.map (disk: {
name = disk;
value =
if cfg.zpool.mode != "stripe" then
makePrimaryZfsDisk {
disk = first;
espSize = cfg.espSize;
swapSize = cfg.swapSize;
legacyBoot = cfg.legacyBoot;
poolName = cfg.zpool.name;
}
else
makeSecondaryZfsDisk {
poolName = cfg.zpool.name;
inherit disk;
};
}) rest
);
in
lib.mkIf cfg.enable {
devices = {
disk = secondaryDisks // {
"${first}" = makePrimaryZfsDisk {
disk = first;
espSize = cfg.espSize;
swapSize = cfg.swapSize;
legacyBoot = cfg.legacyBoot;
poolName = cfg.zpool.name;
};
};
zpool = import ./zpool.nix {
poolName = cfg.zpool.name;
poolMode = cfg.zpool.mode;
poolExtraDatasets = cfg.zpool.extraDatasets;
inherit lib;
};
};
};
};
}
49 changes: 49 additions & 0 deletions modules/mcl-disko/primaryZfsPartition.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
disk,
espSize,
swapSize,
legacyBoot,
poolName,
}:
{
type = "disk";
device = disk;
content = {
type = "gpt";
partitions = {
ESP = {
device = "${disk}-part1";
priority = 0;
size = espSize;
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};

zfs = {
device = "${disk}-part2";
priority = 1;
end = "-${swapSize}";
type = "BF00";
content = {
type = "zfs";
pool = "${poolName}";
};
};

swap = {
device = "${disk}-part3";
priority = 2;
size = if legacyBoot == true then "100%" else swapSize;
content = {
type = "swap";
randomEncryption = true;
};
};
};
};
}
18 changes: 18 additions & 0 deletions modules/mcl-disko/secondaryZfsPartition.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{ poolName, disk }:
{
type = "disk";
device = disk;
content = {
type = "gpt";
partitions = {
zfs = {
device = "${disk}-part1";
size = "100%";
content = {
type = "zfs";
pool = "${poolName}";
};
};
};
};
}
118 changes: 118 additions & 0 deletions modules/mcl-disko/zpool.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
{
lib,
poolName,
poolMode,
poolExtraDatasets,
}:
let
translateDataSetToDiskoConfig =
dataset@{ snapshot, ... }:
lib.recursiveUpdate dataset {
type = "zfs_fs";
options = {
"com.sun:auto-snapshot" = if dataset.snapshot then "on" else "off";
canmount = "on";
};
};

restructuredDatasets = builtins.mapAttrs (
n: v: (builtins.removeAttrs (translateDataSetToDiskoConfig poolExtraDatasets.${n}) [ "snapshot" ])
) poolExtraDatasets;
in
{
${poolName} = {
type = "zpool";
mode = if poolMode == "stripe" then "" else poolMode;
rootFsOptions = {
acltype = "posixacl";
atime = "off";
canmount = "off";
checksum = "sha512";
compression = "lz4";
xattr = "sa";
mountpoint = "none";
"com.sun:auto-snapshot" = "false";
};
options = {
autotrim = "on";
listsnapshots = "on";
};

postCreateHook = "zfs snapshot ${poolName}@blank";

datasets = {
root = {
mountpoint = "/";
type = "zfs_fs";
options = {
"com.sun:auto-snapshot" = "false";
mountpoint = "legacy";
};
};

"root/nix" = {
mountpoint = "/nix";
type = "zfs_fs";
options = {
"com.sun:auto-snapshot" = "false";
canmount = "on";
mountpoint = "legacy";
refreservation = "100GiB";
};
};

"root/var" = {
mountpoint = "/var";
type = "zfs_fs";
options = {
"com.sun:auto-snapshot" = "true";
canmount = "on";
mountpoint = "legacy";
};
};

"root/var/lib" = {
mountpoint = "/var/lib";
type = "zfs_fs";
options = {
"com.sun:auto-snapshot" = "true";
canmount = "on";
mountpoint = "legacy";
};
};

"root/home" = {
mountpoint = "/home";
type = "zfs_fs";
options = {
"com.sun:auto-snapshot" = "true";
canmount = "on";
mountpoint = "legacy";
refreservation = "200GiB";
};
};

"root/var/lib/docker" = {
mountpoint = "/var/lib/docker";
type = "zfs_fs";
options = {
"com.sun:auto-snapshot" = "false";
canmount = "on";
mountpoint = "legacy";
refreservation = "100GiB";
};
};

"root/var/lib/containers" = {
mountpoint = "/var/lib/containers";
type = "zfs_fs";
options = {
"com.sun:auto-snapshot" = "false";
canmount = "on";
mountpoint = "legacy";
refreservation = "100GiB";
};
};
} // restructuredDatasets;
};
}

0 comments on commit 6b33832

Please sign in to comment.