···
1
+
{ config, pkgs, lib, ... }:
3
+
inherit (lib) mapAttrs' nameValuePair filterAttrs types mkEnableOption
4
+
mdDoc mkPackageOptionMD mkOption literalExpression mkIf flatten
5
+
maintainers attrValues;
7
+
cfg = config.services.autosuspend;
9
+
settingsFormat = pkgs.formats.ini { };
13
+
(n: v: nameValuePair "check.${n}" (filterAttrs (_: v: v != null) v))
17
+
(n: v: nameValuePair "wakeup.${n}" (filterAttrs (_: v: v != null) v))
20
+
# Whether the given check is enabled
23
+
(n: v: v.enabled && (if v.class == null then n else v.class) == class)
27
+
# Dependencies needed by specific checks
28
+
dependenciesForChecks = {
30
+
"XIdleTime" = [ pkgs.xprintidle pkgs.sudo ];
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 (mdDoc "this activity check") // { default = true; };
43
+
options.class = mkOption {
45
+
type = with types; nullOr (enum [
46
+
"ActiveCalendarEvent"
54
+
"LogindSessionsIdle"
64
+
description = mdDoc ''
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.
71
+
wakeupType = types.submodule {
72
+
freeformType = settingsFormat.type.nestedTypes.elemType;
74
+
options.enabled = mkEnableOption (mdDoc "this wake-up check") // { default = true; };
76
+
options.class = mkOption {
78
+
type = with types; nullOr (enum [
87
+
description = mdDoc ''
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.
96
+
services.autosuspend = {
97
+
enable = mkEnableOption (mdDoc "the autosuspend daemon");
99
+
package = mkPackageOptionMD pkgs "autosuspend" { };
101
+
settings = mkOption {
102
+
type = types.submodule {
103
+
freeformType = settingsFormat.type.nestedTypes.elemType;
106
+
# Provide reasonable defaults for these two (required) options
107
+
suspend_cmd = mkOption {
108
+
default = "systemctl suspend";
109
+
type = with types; str;
110
+
description = mdDoc ''
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.
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 = mdDoc ''
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.
128
+
example = literalExpression ''
135
+
description = mdDoc ''
136
+
Configuration for autosuspend, see
137
+
<https://autosuspend.readthedocs.io/en/latest/configuration_file.html#general-configuration>
138
+
for supported values.
142
+
checks = mkOption {
144
+
type = with types; attrsOf checkType;
145
+
description = mdDoc ''
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>
150
+
example = literalExpression ''
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.
156
+
hosts = "192.168.0.7";
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.
173
+
# Here the Users activity check is used again with different settings and a different name
178
+
host = "localhost";
184
+
wakeups = mkOption {
186
+
type = with types; attrsOf wakeupType;
187
+
description = mdDoc ''
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>
192
+
example = literalExpression ''
194
+
# Wake up checks reuse the same configuration mechanism as activity checks.
196
+
url = "http://example.org/test.ics";
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));
212
+
ExecStart = ''${autosuspend}/bin/autosuspend -l ${autosuspend}/etc/autosuspend-logging.conf -c ${autosuspend-conf} daemon'';
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" ];
222
+
ExecStart = ''${autosuspend}/bin/autosuspend -l ${autosuspend}/etc/autosuspend-logging.conf -c ${autosuspend-conf} presuspend'';
228
+
maintainers = with maintainers; [ xlambein ];