main
1{
2 lib,
3 den,
4 ...
5}: {
6 den.aspects.disk.btrfs-disko = {
7 includes = [
8 den.aspects.disk.disko
9 den.aspects.disk.btrfs
10 ];
11
12 settings.host = {
13 deviceId = lib.mkOption {
14 type = lib.types.str;
15 default = "";
16 description = ''
17 Disk device id (e.g., "ata-..." or "/dev/disk/by-id/...").
18 If not set, auto-detects a single non-USB disk via facter.
19 '';
20 };
21 swapSize = lib.mkOption {
22 type = lib.types.int;
23 default = 0;
24 description = "Size of swap in MiB, 0 disables swap.";
25 };
26 grubPart = lib.mkOption {
27 type = lib.types.nullOr lib.types.bool;
28 default = null;
29 description = "Whether to creat 1M part for GRUB. Set null to auto detect";
30 };
31 };
32
33 nixos = {
34 config,
35 host,
36 ...
37 }: let
38 cfg = host.settings.disk.btrfs-disko;
39
40 diskDevice =
41 if cfg.deviceId != ""
42 then
43 if lib.hasPrefix "/dev/" cfg.deviceId
44 then cfg.deviceId
45 else "/dev/disk/by-id/" + cfg.deviceId
46 else let
47 native-disks = builtins.filter (f: f.driver != "usb-storage") config.hardware.facter.report.hardware.disk;
48 disk-labels =
49 map (
50 disk:
51 builtins.head (
52 builtins.filter (f: builtins.substring 0 16 f == "/dev/disk/by-id/") disk.unix_device_names
53 )
54 )
55 native-disks;
56 in
57 if (builtins.length disk-labels == 1)
58 then (builtins.head disk-labels)
59 else
60 abort (
61 "Multiple disks found. Please set settings.disk.btrfs-disko.deviceId. Found: "
62 + toString disk-labels
63 );
64
65 defaultBtrfsOpts = [
66 "defaults"
67 "compress=zstd:1"
68 "ssd"
69 "discard=async"
70 ];
71 in {
72 disko.devices = {
73 disk = {
74 main = {
75 device = diskDevice;
76 type = "disk";
77 content = {
78 type = "gpt";
79 partitions = {
80 boot =
81 lib.mkIf
82 (
83 if cfg.grubPart == null
84 then !config.hardware.facter.detected.uefi.supported
85 else cfg.grubPart
86 )
87 {
88 label = "GRUB";
89 size = "1M";
90 type = "EF02";
91 priority = 0;
92 };
93 ESP = {
94 label = "boot";
95 name = "ESP";
96 size = "1G";
97 type = "EF00";
98 priority = 1;
99 content = {
100 type = "filesystem";
101 format = "vfat";
102 mountpoint = "/boot";
103 mountOptions = ["defaults" "umask=0077"];
104 };
105 };
106 nixos = {
107 size = "100%";
108 priority = 2;
109 content = {
110 type = "btrfs";
111 subvolumes =
112 {
113 "/root" = {
114 mountpoint = "/";
115 mountOptions = defaultBtrfsOpts ++ ["noatime"];
116 };
117 "/home" = {
118 mountpoint = "/home";
119 mountOptions = defaultBtrfsOpts ++ ["noatime"];
120 };
121 "/nix" = {
122 mountpoint = "/nix";
123 mountOptions = defaultBtrfsOpts ++ ["noatime"];
124 };
125 "/persist" = lib.mkIf (host.hasAspect den.aspects.disk.preservation) {
126 mountpoint = "/persist";
127 mountOptions = defaultBtrfsOpts;
128 };
129 "/cache" = lib.mkIf (host.hasAspect den.aspects.disk.preservation) {
130 mountpoint = "/cache";
131 mountOptions = defaultBtrfsOpts;
132 };
133 }
134 // lib.optionalAttrs (cfg.swapSize > 0) {
135 "@swap" = {
136 mountpoint = "/swap";
137 swap.swapfile.size = "${toString cfg.swapSize}M";
138 };
139 };
140 };
141 };
142 };
143 };
144 };
145 };
146 };
147
148 fileSystems = {
149 "/nix".neededForBoot = true;
150 "/home".neededForBoot = true;
151 "/persist".neededForBoot = true;
152 "/cache".neededForBoot = true;
153 };
154 };
155 };
156}