1{
2 config,
3 lib,
4 pkgs,
5 ...
6}: let
7 # Compute a list of Btrfs file systems (with mountPoint and device)
8 btrfsFSDevices = let
9 # Helper: does a device already appear in the accumulator?
10 isDeviceInList = list: device:
11 builtins.any (e: e.device == device) list;
12
13 # Helper: keep only the first occurrence of each device
14 uniqueDeviceList = lib.foldl' (
15 acc: e:
16 if isDeviceInList acc e.device
17 then acc
18 else acc ++ [e]
19 ) [];
20 in
21 uniqueDeviceList (
22 lib.mapAttrsToList (_: fs: {
23 inherit (fs) mountPoint device;
24 })
25 (lib.filterAttrs (_: fs: fs.fsType == "btrfs") config.fileSystems)
26 );
27
28 # Create beesd.filesystems attrset keyed by device basename, with spec = device path
29 beesdConfig = lib.listToAttrs (map (fs: {
30 name = lib.strings.sanitizeDerivationName (baseNameOf fs.device);
31
32 value = {
33 # hashTableSizeMB = 2048;
34 # this is ugly but who cares, i can't just get the size of the partition
35 # basically it's like, if it's one /data and on morgana then for sure it's like a terabyte of data, if it's on nanpi then it's 512gb, anything else is my laptop's ssd, 128gb, so 16mb, but could also be the tiny 20gb jezebel disk, as it can't go lower than 16mb
36 hashTableSizeMB =
37 if config.networking.hostName == "morgana" && fs.mountPoint == "/data"
38 then 128
39 else if config.networking.hostName == "nanpi"
40 then 64
41 else 16;
42 spec = fs.device;
43 verbosity = "info";
44
45 extraOptions = [
46 "--loadavg-target"
47 "1.0"
48 "--thread-factor"
49 "0.50"
50 ];
51 };
52 })
53 btrfsFSDevices);
54
55 # Check if a btrfs /home entry exists
56 hasHomeSubvolume =
57 lib.hasAttr "/home" config.fileSystems
58 && config.fileSystems."/home".fsType == "btrfs";
59in {
60 options.myNixOS.profiles.btrfs = {
61 enable = lib.mkEnableOption "btrfs filesystem configuration";
62 deduplicate = lib.mkEnableOption "deduplicate btrfs filesystems";
63 snapshots = lib.mkEnableOption "enable snapper snapshots";
64 };
65
66 config = lib.mkIf config.myNixOS.profiles.btrfs.enable {
67 boot.supportedFilesystems = ["btrfs"];
68 environment.systemPackages = lib.optionals (config.services.xserver.enable && config.myNixOS.profiles.btrfs.snapshots) [pkgs.snapper-gui];
69
70 services = lib.mkIf (btrfsFSDevices != []) {
71 beesd.filesystems = lib.mkIf config.myNixOS.profiles.btrfs.deduplicate beesdConfig;
72 btrfs.autoScrub.enable = true;
73
74 snapper = lib.mkIf config.myNixOS.profiles.btrfs.snapshots {
75 configs.home = lib.mkIf hasHomeSubvolume {
76 ALLOW_GROUPS = ["users"];
77 FSTYPE = "btrfs";
78 SUBVOLUME = "/home";
79 TIMELINE_CLEANUP = true;
80 TIMELINE_CREATE = true;
81 };
82
83 filters = ''
84 -.bash_profile
85 -.bashrc
86 -.cache
87 -.config
88 -.librewolf
89 -.local
90 -.mozilla
91 -.nix-profile
92 -.pki
93 -.share
94 -.snapshots
95 -.thunderbird
96 -.zshrc
97 -.zen
98 -.steam
99 -.npm
100 '';
101
102 persistentTimer = true;
103 };
104 };
105 };
106}