grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / misc / autosuspend.nix
bloba41ad43c44297ed24381e093755d604dd514cdf8
1 { config, pkgs, lib, ... }:
2 let
3   inherit (lib) mapAttrs' nameValuePair filterAttrs types mkEnableOption
4     mkPackageOption mkOption literalExpression mkIf flatten
5     maintainers attrValues;
7   cfg = config.services.autosuspend;
9   settingsFormat = pkgs.formats.ini { };
11   checks =
12     mapAttrs'
13       (n: v: nameValuePair "check.${n}" (filterAttrs (_: v: v != null) v))
14       cfg.checks;
15   wakeups =
16     mapAttrs'
17       (n: v: nameValuePair "wakeup.${n}" (filterAttrs (_: v: v != null) v))
18       cfg.wakeups;
20   # Whether the given check is enabled
21   hasCheck = class:
22     (filterAttrs
23       (n: v: v.enabled && (if v.class == null then n else v.class) == class)
24       cfg.checks)
25     != { };
27   # Dependencies needed by specific checks
28   dependenciesForChecks = {
29     "Smb" = pkgs.samba;
30     "XIdleTime" = [ pkgs.xprintidle pkgs.sudo ];
31   };
33   autosuspend-conf =
34     settingsFormat.generate "autosuspend.conf" ({ general = cfg.settings; } // checks // wakeups);
36   autosuspend = cfg.package;
38   checkType = types.submodule {
39     freeformType = settingsFormat.type.nestedTypes.elemType;
41     options.enabled = mkEnableOption "this activity check" // { default = true; };
43     options.class = mkOption {
44       default = null;
45       type = with types; nullOr (enum [
46         "ActiveCalendarEvent"
47         "ActiveConnection"
48         "ExternalCommand"
49         "JsonPath"
50         "Kodi"
51         "KodiIdleTime"
52         "LastLogActivity"
53         "Load"
54         "LogindSessionsIdle"
55         "Mpd"
56         "NetworkBandwidth"
57         "Ping"
58         "Processes"
59         "Smb"
60         "Users"
61         "XIdleTime"
62         "XPath"
63       ]);
64       description = ''
65         Name of the class implementing the check.  If this option is not specified, the check's
66         name must represent a valid internal check class.
67       '';
68     };
69   };
71   wakeupType = types.submodule {
72     freeformType = settingsFormat.type.nestedTypes.elemType;
74     options.enabled = mkEnableOption "this wake-up check" // { default = true; };
76     options.class = mkOption {
77       default = null;
78       type = with types; nullOr (enum [
79         "Calendar"
80         "Command"
81         "File"
82         "Periodic"
83         "SystemdTimer"
84         "XPath"
85         "XPathDelta"
86       ]);
87       description = ''
88         Name of the class implementing the check.  If this option is not specified, the check's
89         name must represent a valid internal check class.
90       '';
91     };
92   };
95   options = {
96     services.autosuspend = {
97       enable = mkEnableOption "the autosuspend daemon";
99       package = mkPackageOption pkgs "autosuspend" { };
101       settings = mkOption {
102         type = types.submodule {
103           freeformType = settingsFormat.type.nestedTypes.elemType;
105           options = {
106             # Provide reasonable defaults for these two (required) options
107             suspend_cmd = mkOption {
108               default = "systemctl suspend";
109               type = with types; str;
110               description = ''
111                 The command to execute in case the host shall be suspended. This line can contain
112                 additional command line arguments to the command to execute.
113               '';
114             };
115             wakeup_cmd = mkOption {
116               default = ''sh -c 'echo 0 > /sys/class/rtc/rtc0/wakealarm && echo {timestamp:.0f} > /sys/class/rtc/rtc0/wakealarm' '';
117               type = with types; str;
118               description = ''
119                 The command to execute for scheduling a wake up of the system. The given string is
120                 processed using Python’s `str.format()` and a format argument called `timestamp`
121                 encodes the UTC timestamp of the planned wake up time (float). Additionally `iso`
122                 can be used to acquire the timestamp in ISO 8601 format.
123               '';
124             };
125           };
126         };
127         default = { };
128         example = literalExpression ''
129           {
130             enable = true;
131             interval = 30;
132             idle_time = 120;
133           }
134         '';
135         description = ''
136           Configuration for autosuspend, see
137           <https://autosuspend.readthedocs.io/en/latest/configuration_file.html#general-configuration>
138           for supported values.
139         '';
140       };
142       checks = mkOption {
143         default = { };
144         type = with types; attrsOf checkType;
145         description = ''
146           Checks for activity.  For more information, see:
147            - <https://autosuspend.readthedocs.io/en/latest/configuration_file.html#activity-check-configuration>
148            - <https://autosuspend.readthedocs.io/en/latest/available_checks.html>
149         '';
150         example = literalExpression ''
151           {
152             # Basic activity check configuration.
153             # The check class name is derived from the section header (Ping in this case).
154             # Remember to enable desired checks. They are disabled by default.
155             Ping = {
156               hosts = "192.168.0.7";
157             };
159             # This check is disabled.
160             Smb.enabled = false;
162             # Example for a custom check name.
163             # This will use the Users check with the custom name RemoteUsers.
164             # Custom names are necessary in case a check class is used multiple times.
165             # Custom names can also be used for clarification.
166             RemoteUsers = {
167               class = "Users";
168               name = ".*";
169               terminal = ".*";
170               host = "[0-9].*";
171             };
173             # Here the Users activity check is used again with different settings and a different name
174             LocalUsers = {
175               class = "Users";
176               name = ".*";
177               terminal = ".*";
178               host = "localhost";
179             };
180           }
181         '';
182       };
184       wakeups = mkOption {
185         default = { };
186         type = with types; attrsOf wakeupType;
187         description = ''
188           Checks for wake up.  For more information, see:
189            - <https://autosuspend.readthedocs.io/en/latest/configuration_file.html#wake-up-check-configuration>
190            - <https://autosuspend.readthedocs.io/en/latest/available_wakeups.html>
191         '';
192         example = literalExpression ''
193           {
194             # Wake up checks reuse the same configuration mechanism as activity checks.
195             Calendar = {
196               url = "http://example.org/test.ics";
197             };
198           }
199         '';
200       };
201     };
202   };
204   config = mkIf cfg.enable {
205     systemd.services.autosuspend = {
206       description = "A daemon to suspend your server in case of inactivity";
207       documentation = [ "https://autosuspend.readthedocs.io/en/latest/systemd_integration.html" ];
208       wantedBy = [ "multi-user.target" ];
209       after = [ "network.target" ];
210       path = flatten (attrValues (filterAttrs (n: _: hasCheck n) dependenciesForChecks));
211       serviceConfig = {
212         ExecStart = ''${autosuspend}/bin/autosuspend -l ${autosuspend}/etc/autosuspend-logging.conf -c ${autosuspend-conf} daemon'';
213       };
214     };
216     systemd.services.autosuspend-detect-suspend = {
217       description = "Notifies autosuspend about suspension";
218       documentation = [ "https://autosuspend.readthedocs.io/en/latest/systemd_integration.html" ];
219       wantedBy = [ "sleep.target" ];
220       after = [ "sleep.target" ];
221       serviceConfig = {
222         ExecStart = ''${autosuspend}/bin/autosuspend -l ${autosuspend}/etc/autosuspend-logging.conf -c ${autosuspend-conf} presuspend'';
223       };
224     };
225   };
227   meta = {
228     maintainers = with maintainers; [ xlambein ];
229   };