grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / misc / bees.nix
blob0824e0a8835c2a7a33335f9e7e35cb12eb116f20
1 { config, lib, pkgs, ... }:
2 let
4   cfg = config.services.beesd;
6   logLevels = { emerg = 0; alert = 1; crit = 2; err = 3; warning = 4; notice = 5; info = 6; debug = 7; };
8   fsOptions = with lib.types; {
9     options.spec = lib.mkOption {
10       type = str;
11       description = ''
12         Description of how to identify the filesystem to be duplicated by this
13         instance of bees. Note that deduplication crosses subvolumes; one must
14         not configure multiple instances for subvolumes of the same filesystem
15         (or block devices which are part of the same filesystem), but only for
16         completely independent btrfs filesystems.
18         This must be in a format usable by findmnt; that could be a key=value
19         pair, or a bare path to a mount point.
20         Using bare paths will allow systemd to start the beesd service only
21         after mounting the associated path.
22       '';
23       example = "LABEL=MyBulkDataDrive";
24     };
25     options.hashTableSizeMB = lib.mkOption {
26       type = lib.types.addCheck lib.types.int (n: lib.mod n 16 == 0);
27       default = 1024; # 1GB; default from upstream beesd script
28       description = ''
29         Hash table size in MB; must be a multiple of 16.
31         A larger ratio of index size to storage size means smaller blocks of
32         duplicate content are recognized.
34         If you have 1TB of data, a 4GB hash table (which is to say, a value of
35         4096) will permit 4KB extents (the smallest possible size) to be
36         recognized, whereas a value of 1024 -- creating a 1GB hash table --
37         will recognize only aligned duplicate blocks of 16KB.
38       '';
39     };
40     options.verbosity = lib.mkOption {
41       type = lib.types.enum (lib.attrNames logLevels ++ lib.attrValues logLevels);
42       apply = v: if lib.isString v then logLevels.${v} else v;
43       default = "info";
44       description = "Log verbosity (syslog keyword/level).";
45     };
46     options.workDir = lib.mkOption {
47       type = str;
48       default = ".beeshome";
49       description = ''
50         Name (relative to the root of the filesystem) of the subvolume where
51         the hash table will be stored.
52       '';
53     };
54     options.extraOptions = lib.mkOption {
55       type = listOf str;
56       default = [ ];
57       description = ''
58         Extra command-line options passed to the daemon. See upstream bees documentation.
59       '';
60       example = lib.literalExpression ''
61         [ "--thread-count" "4" ]
62       '';
63     };
64   };
69   options.services.beesd = {
70     filesystems = lib.mkOption {
71       type = with lib.types; attrsOf (submodule fsOptions);
72       description = "BTRFS filesystems to run block-level deduplication on.";
73       default = { };
74       example = lib.literalExpression ''
75         {
76           root = {
77             spec = "LABEL=root";
78             hashTableSizeMB = 2048;
79             verbosity = "crit";
80             extraOptions = [ "--loadavg-target" "5.0" ];
81           };
82         }
83       '';
84     };
85   };
86   config = {
87     systemd.services = lib.mapAttrs'
88       (name: fs: lib.nameValuePair "beesd@${name}" {
89         description = "Block-level BTRFS deduplication for %i";
90         after = [ "sysinit.target" ];
92         serviceConfig =
93           let
94             configOpts = [
95               fs.spec
96               "verbosity=${toString fs.verbosity}"
97               "idxSizeMB=${toString fs.hashTableSizeMB}"
98               "workDir=${fs.workDir}"
99             ];
100             configOptsStr = lib.escapeShellArgs configOpts;
101           in
102           {
103             # Values from https://github.com/Zygo/bees/blob/v0.6.5/scripts/beesd@.service.in
104             ExecStart = "${pkgs.bees}/bin/bees-service-wrapper run ${configOptsStr} -- --no-timestamps ${lib.escapeShellArgs fs.extraOptions}";
105             ExecStopPost = "${pkgs.bees}/bin/bees-service-wrapper cleanup ${configOptsStr}";
106             CPUAccounting = true;
107             CPUSchedulingPolicy = "batch";
108             CPUWeight = 12;
109             IOSchedulingClass = "idle";
110             IOSchedulingPriority = 7;
111             IOWeight = 10;
112             KillMode = "control-group";
113             KillSignal = "SIGTERM";
114             MemoryAccounting = true;
115             Nice = 19;
116             Restart = "on-abnormal";
117             StartupCPUWeight = 25;
118             StartupIOWeight = 25;
119             SyslogIdentifier = "beesd"; # would otherwise be "bees-service-wrapper"
120           };
121         unitConfig.RequiresMountsFor = lib.mkIf (lib.hasPrefix "/" fs.spec) fs.spec;
122         wantedBy = [ "multi-user.target" ];
123       })
124       cfg.filesystems;
125   };