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 = {
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 };
27
28 nixos = {
29 config,
30 host,
31 ...
32 }: let
33 cfg = host.settings.disk.btrfs-disko;
34
35 diskDevice =
36 if cfg.deviceId != ""
37 then
38 if lib.hasPrefix "/dev/" cfg.deviceId
39 then cfg.deviceId
40 else "/dev/disk/by-id/" + cfg.deviceId
41 else let
42 native-disks = builtins.filter (f: f.driver != "usb-storage") config.hardware.facter.report.hardware.disk;
43 disk-labels =
44 map (
45 disk:
46 builtins.head (
47 builtins.filter (f: builtins.substring 0 16 f == "/dev/disk/by-id/") disk.unix_device_names
48 )
49 )
50 native-disks;
51 in
52 if (builtins.length disk-labels == 1)
53 then (builtins.head disk-labels)
54 else
55 abort (
56 "Multiple disks found. Please set settings.disk.btrfs-disko.deviceId. Found: "
57 + toString disk-labels
58 );
59
60 defaultBtrfsOpts = [
61 "defaults"
62 "compress=zstd:1"
63 "ssd"
64 "discard=async"
65 ];
66 in {
67 disko.devices = {
68 disk = {
69 main = {
70 device = diskDevice;
71 type = "disk";
72 content = {
73 type = "gpt";
74 partitions = {
75 boot = lib.mkIf (!config.hardware.facter.report.uefi.supported) {
76 label = "GRUB";
77 size = "1M";
78 type = "EF02";
79 priority = 0;
80 };
81 ESP = {
82 label = "boot";
83 name = "ESP";
84 size = "512M";
85 type = "EF00";
86 priority = 1;
87 content = {
88 type = "filesystem";
89 format = "vfat";
90 mountpoint = "/boot";
91 mountOptions = ["defaults"];
92 };
93 };
94 nixos = {
95 size = "100%";
96 priority = 2;
97 content = {
98 type = "btrfs";
99 subvolumes =
100 {
101 "/root" = {
102 mountpoint = "/";
103 mountOptions = defaultBtrfsOpts ++ ["noatime"];
104 };
105 "/home" = {
106 mountpoint = "/home";
107 mountOptions = defaultBtrfsOpts ++ ["noatime"];
108 };
109 "/nix" = {
110 mountpoint = "/nix";
111 mountOptions = defaultBtrfsOpts ++ ["noatime"];
112 };
113 "/persist" = lib.mkIf (host.hasAspect den.aspects.core.impermanence) {
114 mountpoint = "/persist";
115 mountOptions = defaultBtrfsOpts;
116 };
117 "/cache" = lib.mkIf (host.hasAspect den.aspects.core.impermanence) {
118 mountpoint = "/cache";
119 mountOptions = defaultBtrfsOpts;
120 };
121 }
122 // lib.optionalAttrs (cfg.swapSize > 0) {
123 "@swap" = {
124 mountpoint = "/swap";
125 swap.swapfile.size = "${toString cfg.swapSize}M";
126 };
127 };
128 };
129 };
130 };
131 };
132 };
133 };
134 };
135
136 fileSystems = {
137 "/nix".neededForBoot = true;
138 "/home".neededForBoot = true;
139 "/persist".neededForBoot = true;
140 "/cache".neededForBoot = true;
141 };
142 };
143 };
144}