about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/services/misc/autosuspend.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/services/misc/autosuspend.nix')
-rw-r--r--nixpkgs/nixos/modules/services/misc/autosuspend.nix230
1 files changed, 230 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/misc/autosuspend.nix b/nixpkgs/nixos/modules/services/misc/autosuspend.nix
new file mode 100644
index 000000000000..28dfa12105ec
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/autosuspend.nix
@@ -0,0 +1,230 @@
+{ config, pkgs, lib, ... }:
+let
+  inherit (lib) mapAttrs' nameValuePair filterAttrs types mkEnableOption
+    mdDoc mkPackageOption mkOption literalExpression mkIf flatten
+    maintainers attrValues;
+
+  cfg = config.services.autosuspend;
+
+  settingsFormat = pkgs.formats.ini { };
+
+  checks =
+    mapAttrs'
+      (n: v: nameValuePair "check.${n}" (filterAttrs (_: v: v != null) v))
+      cfg.checks;
+  wakeups =
+    mapAttrs'
+      (n: v: nameValuePair "wakeup.${n}" (filterAttrs (_: v: v != null) v))
+      cfg.wakeups;
+
+  # Whether the given check is enabled
+  hasCheck = class:
+    (filterAttrs
+      (n: v: v.enabled && (if v.class == null then n else v.class) == class)
+      cfg.checks)
+    != { };
+
+  # Dependencies needed by specific checks
+  dependenciesForChecks = {
+    "Smb" = pkgs.samba;
+    "XIdleTime" = [ pkgs.xprintidle pkgs.sudo ];
+  };
+
+  autosuspend-conf =
+    settingsFormat.generate "autosuspend.conf" ({ general = cfg.settings; } // checks // wakeups);
+
+  autosuspend = cfg.package;
+
+  checkType = types.submodule {
+    freeformType = settingsFormat.type.nestedTypes.elemType;
+
+    options.enabled = mkEnableOption (mdDoc "this activity check") // { default = true; };
+
+    options.class = mkOption {
+      default = null;
+      type = with types; nullOr (enum [
+        "ActiveCalendarEvent"
+        "ActiveConnection"
+        "ExternalCommand"
+        "JsonPath"
+        "Kodi"
+        "KodiIdleTime"
+        "LastLogActivity"
+        "Load"
+        "LogindSessionsIdle"
+        "Mpd"
+        "NetworkBandwidth"
+        "Ping"
+        "Processes"
+        "Smb"
+        "Users"
+        "XIdleTime"
+        "XPath"
+      ]);
+      description = mdDoc ''
+        Name of the class implementing the check.  If this option is not specified, the check's
+        name must represent a valid internal check class.
+      '';
+    };
+  };
+
+  wakeupType = types.submodule {
+    freeformType = settingsFormat.type.nestedTypes.elemType;
+
+    options.enabled = mkEnableOption (mdDoc "this wake-up check") // { default = true; };
+
+    options.class = mkOption {
+      default = null;
+      type = with types; nullOr (enum [
+        "Calendar"
+        "Command"
+        "File"
+        "Periodic"
+        "SystemdTimer"
+        "XPath"
+        "XPathDelta"
+      ]);
+      description = mdDoc ''
+        Name of the class implementing the check.  If this option is not specified, the check's
+        name must represent a valid internal check class.
+      '';
+    };
+  };
+in
+{
+  options = {
+    services.autosuspend = {
+      enable = mkEnableOption (mdDoc "the autosuspend daemon");
+
+      package = mkPackageOption pkgs "autosuspend" { };
+
+      settings = mkOption {
+        type = types.submodule {
+          freeformType = settingsFormat.type.nestedTypes.elemType;
+
+          options = {
+            # Provide reasonable defaults for these two (required) options
+            suspend_cmd = mkOption {
+              default = "systemctl suspend";
+              type = with types; str;
+              description = mdDoc ''
+                The command to execute in case the host shall be suspended. This line can contain
+                additional command line arguments to the command to execute.
+              '';
+            };
+            wakeup_cmd = mkOption {
+              default = ''sh -c 'echo 0 > /sys/class/rtc/rtc0/wakealarm && echo {timestamp:.0f} > /sys/class/rtc/rtc0/wakealarm' '';
+              type = with types; str;
+              description = mdDoc ''
+                The command to execute for scheduling a wake up of the system. The given string is
+                processed using Python’s `str.format()` and a format argument called `timestamp`
+                encodes the UTC timestamp of the planned wake up time (float). Additionally `iso`
+                can be used to acquire the timestamp in ISO 8601 format.
+              '';
+            };
+          };
+        };
+        default = { };
+        example = literalExpression ''
+          {
+            enable = true;
+            interval = 30;
+            idle_time = 120;
+          }
+        '';
+        description = mdDoc ''
+          Configuration for autosuspend, see
+          <https://autosuspend.readthedocs.io/en/latest/configuration_file.html#general-configuration>
+          for supported values.
+        '';
+      };
+
+      checks = mkOption {
+        default = { };
+        type = with types; attrsOf checkType;
+        description = mdDoc ''
+          Checks for activity.  For more information, see:
+           - <https://autosuspend.readthedocs.io/en/latest/configuration_file.html#activity-check-configuration>
+           - <https://autosuspend.readthedocs.io/en/latest/available_checks.html>
+        '';
+        example = literalExpression ''
+          {
+            # Basic activity check configuration.
+            # The check class name is derived from the section header (Ping in this case).
+            # Remember to enable desired checks. They are disabled by default.
+            Ping = {
+              hosts = "192.168.0.7";
+            };
+
+            # This check is disabled.
+            Smb.enabled = false;
+
+            # Example for a custom check name.
+            # This will use the Users check with the custom name RemoteUsers.
+            # Custom names are necessary in case a check class is used multiple times.
+            # Custom names can also be used for clarification.
+            RemoteUsers = {
+              class = "Users";
+              name = ".*";
+              terminal = ".*";
+              host = "[0-9].*";
+            };
+
+            # Here the Users activity check is used again with different settings and a different name
+            LocalUsers = {
+              class = "Users";
+              name = ".*";
+              terminal = ".*";
+              host = "localhost";
+            };
+          }
+        '';
+      };
+
+      wakeups = mkOption {
+        default = { };
+        type = with types; attrsOf wakeupType;
+        description = mdDoc ''
+          Checks for wake up.  For more information, see:
+           - <https://autosuspend.readthedocs.io/en/latest/configuration_file.html#wake-up-check-configuration>
+           - <https://autosuspend.readthedocs.io/en/latest/available_wakeups.html>
+        '';
+        example = literalExpression ''
+          {
+            # Wake up checks reuse the same configuration mechanism as activity checks.
+            Calendar = {
+              url = "http://example.org/test.ics";
+            };
+          }
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.autosuspend = {
+      description = "A daemon to suspend your server in case of inactivity";
+      documentation = [ "https://autosuspend.readthedocs.io/en/latest/systemd_integration.html" ];
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      path = flatten (attrValues (filterAttrs (n: _: hasCheck n) dependenciesForChecks));
+      serviceConfig = {
+        ExecStart = ''${autosuspend}/bin/autosuspend -l ${autosuspend}/etc/autosuspend-logging.conf -c ${autosuspend-conf} daemon'';
+      };
+    };
+
+    systemd.services.autosuspend-detect-suspend = {
+      description = "Notifies autosuspend about suspension";
+      documentation = [ "https://autosuspend.readthedocs.io/en/latest/systemd_integration.html" ];
+      wantedBy = [ "sleep.target" ];
+      after = [ "sleep.target" ];
+      serviceConfig = {
+        ExecStart = ''${autosuspend}/bin/autosuspend -l ${autosuspend}/etc/autosuspend-logging.conf -c ${autosuspend-conf} presuspend'';
+      };
+    };
+  };
+
+  meta = {
+    maintainers = with maintainers; [ xlambein ];
+  };
+}