Skip to content

Commit 64c72e9

Browse files
committed
feat(modules/mcl-disko): Create ZFS configuration module
1 parent d75be2f commit 64c72e9

File tree

5 files changed

+397
-0
lines changed

5 files changed

+397
-0
lines changed

modules/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
./folder-size-metrics
77
./shard-split
88
./random-alerts
9+
./mcl-disko
910
];
1011
}

modules/mcl-disko/default.nix

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
{ withSystem, inputs, ... }:
2+
{
3+
flake.modules.nixos.mcl-disko =
4+
{
5+
pkgs,
6+
config,
7+
lib,
8+
...
9+
}:
10+
with lib;
11+
let
12+
cfg = config.mcl.disko;
13+
in
14+
{
15+
imports = [
16+
inputs.disko.nixosModules.disko
17+
];
18+
options.mcl.disko = {
19+
enable = mkEnableOption "Enable Module";
20+
21+
legacyBoot = mkOption {
22+
type = types.bool;
23+
default = false;
24+
example = true;
25+
description = "Declare if the configuration is for a Hetzner server or not";
26+
};
27+
28+
swapSize = mkOption {
29+
type = types.str;
30+
default = "32G";
31+
example = "32768M";
32+
description = "The size of the hard disk space used when RAM is full";
33+
};
34+
35+
espSize = mkOption {
36+
type = types.str;
37+
default = "4G";
38+
example = "4096M";
39+
description = "The size of the hard disk space used for the ESP filesystem";
40+
};
41+
42+
disks = mkOption {
43+
type = types.listOf types.str;
44+
default = [ ];
45+
example = [
46+
"/dev/disk/sda"
47+
"/dev/disk/sdb"
48+
"/dev/disk/sdc"
49+
];
50+
description = "The disk partitions to be used when ZFS is being created";
51+
};
52+
53+
disksNames = mkOption {
54+
type = types.listOf types.str;
55+
default = cfg.disks;
56+
example = [
57+
"sda"
58+
"sdb"
59+
"sdc"
60+
];
61+
description = "The disk partitions names to be used when ZFS is being created";
62+
};
63+
64+
zpool = {
65+
name = mkOption {
66+
type = types.str;
67+
default = "zfs_root";
68+
description = "The name of the ZFS Pool";
69+
};
70+
71+
mode = mkOption {
72+
type = types.enum [
73+
"stripe"
74+
"mirror"
75+
"raidz1"
76+
"raidz2"
77+
"raidz3"
78+
];
79+
default = "stripe";
80+
description = "Set ZFS Pool redundancy - e.g. 'mirror', 'raidz1', etc.";
81+
};
82+
83+
extraDatasets = mkOption {
84+
type = types.attrsOf (
85+
types.submodule (
86+
{ name, ... }:
87+
{
88+
options = {
89+
mountpoint = mkOption {
90+
type = types.nullOr types.str;
91+
default = name;
92+
example = "/var/lib";
93+
description = "The ZFS dataset mountpoint";
94+
};
95+
96+
type = mkOption {
97+
type = types.enum [
98+
"zfs_fs"
99+
"zfs_volume"
100+
];
101+
default = "zfs_fs";
102+
description = "Type of ZFS dataset";
103+
};
104+
105+
options = mkOption {
106+
type = types.attrs;
107+
default = { };
108+
example = {
109+
refreservation = "50G";
110+
};
111+
description = "";
112+
};
113+
114+
snapshot = mkEnableOption "Whether to enable ZFS snapshots";
115+
116+
refreservation = mkOption {
117+
type = types.nullOr types.str;
118+
default = null;
119+
description = "Size of reservations";
120+
};
121+
};
122+
}
123+
)
124+
);
125+
default = { };
126+
example = {
127+
"/opt".snapshot = false;
128+
"/opt/downloads".snapshot = false;
129+
"/opt/downloads/vm-images" = {
130+
snapshot = false;
131+
options = {
132+
quota = "120G";
133+
};
134+
};
135+
};
136+
description = "Extra ZFS Pool datasets";
137+
};
138+
};
139+
};
140+
141+
config.disko =
142+
let
143+
makePrimaryZfsDisk = import ./primaryZfsPartition.nix;
144+
makeSecondaryZfsDisk = import ./secondaryZfsPartition.nix;
145+
146+
first = builtins.head cfg.disks;
147+
rest = builtins.tail cfg.disks;
148+
149+
firstDiskName = builtins.head cfg.disksNames;
150+
restDisksNames = builtins.tail cfg.disksNames;
151+
152+
secondaryDisks = builtins.listToAttrs (
153+
lib.zipListsWith (disk: diskName: {
154+
name = diskName;
155+
value =
156+
if cfg.zpool.mode != "stripe" then
157+
makePrimaryZfsDisk {
158+
inherit disk lib;
159+
isSecondary = true;
160+
espSize = cfg.espSize;
161+
swapSize = cfg.swapSize;
162+
legacyBoot = cfg.legacyBoot;
163+
poolName = cfg.zpool.name;
164+
}
165+
else
166+
makeSecondaryZfsDisk {
167+
poolName = cfg.zpool.name;
168+
inherit disk lib;
169+
};
170+
}) rest restDisksNames
171+
);
172+
173+
in
174+
lib.mkIf cfg.enable {
175+
devices = {
176+
disk = secondaryDisks // {
177+
"${firstDiskName}" = makePrimaryZfsDisk {
178+
inherit lib;
179+
disk = first;
180+
isSecondary = false;
181+
espSize = cfg.espSize;
182+
swapSize = cfg.swapSize;
183+
legacyBoot = cfg.legacyBoot;
184+
poolName = cfg.zpool.name;
185+
};
186+
};
187+
zpool = import ./zpool.nix {
188+
poolName = cfg.zpool.name;
189+
poolMode = cfg.zpool.mode;
190+
poolExtraDatasets = cfg.zpool.extraDatasets;
191+
inherit lib;
192+
};
193+
};
194+
};
195+
};
196+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
lib,
3+
disk,
4+
isSecondary,
5+
espSize,
6+
swapSize,
7+
legacyBoot,
8+
poolName,
9+
}:
10+
{
11+
type = "disk";
12+
device = disk;
13+
content = {
14+
type = "gpt";
15+
partitions =
16+
lib.optionals legacyBoot {
17+
"boot" = {
18+
size = "1MiB";
19+
type = "EF02";
20+
};
21+
}
22+
// {
23+
"ESP" = {
24+
device = "${disk}-part1";
25+
size = espSize;
26+
type = "EF00";
27+
bootable = true;
28+
content = {
29+
type = "filesystem";
30+
format = "vfat";
31+
mountpoint = if isSecondary then null else "/boot";
32+
mountOptions = [ "umask=0077" ];
33+
};
34+
};
35+
"zfs" = {
36+
device = "${disk}-part2";
37+
end = "-${swapSize}";
38+
type = "BF00";
39+
content = {
40+
type = "zfs";
41+
pool = "${poolName}";
42+
};
43+
};
44+
45+
"swap" = {
46+
device = "${disk}-part3";
47+
size = swapSize;
48+
content = {
49+
type = "swap";
50+
randomEncryption = true;
51+
};
52+
};
53+
};
54+
};
55+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
lib,
3+
poolName,
4+
disk,
5+
disk-names,
6+
}:
7+
{
8+
type = "disk";
9+
device = disk;
10+
content = {
11+
type = "gpt";
12+
partitions = {
13+
zfs = {
14+
device = "${disk}-part1";
15+
size = "100%";
16+
content = {
17+
type = "zfs";
18+
pool = "${poolName}";
19+
};
20+
};
21+
};
22+
};
23+
}

0 commit comments

Comments
 (0)