1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9 cfg = config.services.ananicy;
10 configFile = pkgs.writeText "ananicy.conf" (lib.generators.toKeyValue { } cfg.settings);
11 extraRules = pkgs.writeText "extraRules" (
12 lib.concatMapStringsSep "\n" (l: builtins.toJSON l) cfg.extraRules
13 );
14 extraTypes = pkgs.writeText "extraTypes" (
15 lib.concatMapStringsSep "\n" (l: builtins.toJSON l) cfg.extraTypes
16 );
17 extraCgroups = pkgs.writeText "extraCgroups" (
18 lib.concatMapStringsSep "\n" (l: builtins.toJSON l) cfg.extraCgroups
19 );
20 servicename =
21 if ((lib.getName cfg.package) == (lib.getName pkgs.ananicy-cpp)) then "ananicy-cpp" else "ananicy";
22in
23{
24 options.services.ananicy = {
25 enable = lib.mkEnableOption "Ananicy, an auto nice daemon";
26
27 package = lib.mkPackageOption pkgs "ananicy" { example = "ananicy-cpp"; };
28
29 rulesProvider = lib.mkPackageOption pkgs "ananicy" { example = "ananicy-cpp"; } // {
30 description = ''
31 Which package to copy default rules,types,cgroups from.
32 '';
33 };
34
35 settings = lib.mkOption {
36 type =
37 with lib.types;
38 attrsOf (oneOf [
39 int
40 bool
41 str
42 ]);
43 default = { };
44 example = {
45 apply_nice = false;
46 };
47 description = ''
48 See <https://github.com/Nefelim4ag/Ananicy/blob/master/ananicy.d/ananicy.conf>
49 '';
50 };
51
52 extraRules = lib.mkOption {
53 type = with lib.types; listOf attrs;
54 default = [ ];
55 description = ''
56 Rules to write in 'nixRules.rules'. See:
57 <https://github.com/Nefelim4ag/Ananicy#configuration>
58 <https://gitlab.com/ananicy-cpp/ananicy-cpp/#global-configuration>
59 '';
60 example = [
61 {
62 name = "eog";
63 type = "Image-Viewer";
64 }
65 {
66 name = "fdupes";
67 type = "BG_CPUIO";
68 }
69 ];
70 };
71 extraTypes = lib.mkOption {
72 type = with lib.types; listOf attrs;
73 default = [ ];
74 description = ''
75 Types to write in 'nixTypes.types'. See:
76 <https://gitlab.com/ananicy-cpp/ananicy-cpp/#types>
77 '';
78 example = [
79 {
80 type = "my_type";
81 nice = 19;
82 other_parameter = "value";
83 }
84 {
85 type = "compiler";
86 nice = 19;
87 sched = "batch";
88 ioclass = "idle";
89 }
90 ];
91 };
92 extraCgroups = lib.mkOption {
93 type = with lib.types; listOf attrs;
94 default = [ ];
95 description = ''
96 Cgroups to write in 'nixCgroups.cgroups'. See:
97 <https://gitlab.com/ananicy-cpp/ananicy-cpp/#cgroups>
98 '';
99 example = [
100 {
101 cgroup = "cpu80";
102 CPUQuota = 80;
103 }
104 ];
105 };
106 };
107
108 config = lib.mkIf cfg.enable {
109 environment = {
110 systemPackages = [ cfg.package ];
111 etc."ananicy.d".source =
112 pkgs.runCommand "ananicyfiles"
113 {
114 preferLocalBuild = true;
115 }
116 ''
117 mkdir -p $out
118 # ananicy-cpp does not include rules or settings on purpose
119 if [[ -d "${cfg.rulesProvider}/etc/ananicy.d/00-default" ]]; then
120 cp -r ${cfg.rulesProvider}/etc/ananicy.d/* $out
121 else
122 cp -r ${cfg.rulesProvider}/* $out
123 fi
124
125 # configured through .setings
126 rm -f $out/ananicy.conf
127 cp ${configFile} $out/ananicy.conf
128 ${lib.optionalString (cfg.extraRules != [ ]) "cp ${extraRules} $out/nixRules.rules"}
129 ${lib.optionalString (cfg.extraTypes != [ ]) "cp ${extraTypes} $out/nixTypes.types"}
130 ${lib.optionalString (cfg.extraCgroups != [ ]) "cp ${extraCgroups} $out/nixCgroups.cgroups"}
131 '';
132 };
133
134 # ananicy and ananicy-cpp have different default settings
135 services.ananicy.settings =
136 let
137 mkOD = lib.mkOptionDefault;
138 in
139 {
140 cgroup_load = mkOD true;
141 type_load = mkOD true;
142 rule_load = mkOD true;
143 apply_nice = mkOD true;
144 apply_ioclass = mkOD true;
145 apply_ionice = mkOD true;
146 apply_sched = mkOD true;
147 apply_oom_score_adj = mkOD true;
148 apply_cgroup = mkOD true;
149 }
150 // (
151 if servicename == "ananicy-cpp" then
152 {
153 # https://gitlab.com/ananicy-cpp/ananicy-cpp/-/blob/master/src/config.cpp#L12
154 loglevel = mkOD "warn"; # default is info but its spammy
155 cgroup_realtime_workaround = true;
156 log_applied_rule = mkOD false;
157 }
158 else
159 {
160 # https://github.com/Nefelim4ag/Ananicy/blob/master/ananicy.d/ananicy.conf
161 check_disks_schedulers = mkOD true;
162 check_freq = mkOD 5;
163 }
164 );
165
166 systemd = {
167 packages = [ cfg.package ];
168 services."${servicename}" = {
169 wantedBy = [ "default.target" ];
170 };
171 };
172 };
173
174 meta.maintainers = with lib.maintainers; [ artturin ];
175}