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