From 5907cbbb31d9de387349efb825864a9ee598e6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20B=C3=B8rgesen?= Date: Sat, 18 Nov 2023 14:18:06 +0100 Subject: [PATCH 1/2] networking: Add wakeOnLan option --- modules/networking/default.nix | 16 ++++++++++++++++ tests/networking-wakeonlan.nix | 10 ++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/networking-wakeonlan.nix diff --git a/modules/networking/default.nix b/modules/networking/default.nix index 099c705e..b53a9e4a 100644 --- a/modules/networking/default.nix +++ b/modules/networking/default.nix @@ -9,6 +9,8 @@ let emptyList = lst: if lst != [] then lst else ["empty"]; + onOff = cond: if cond then "on" else "off"; + setNetworkServices = optionalString (cfg.knownNetworkServices != []) '' networkservices=$(networksetup -listallnetworkservices) ${concatMapStringsSep "\n" (srv: '' @@ -93,6 +95,16 @@ in default = []; description = "The list of search paths used when resolving domain names."; }; + + networking.wakeOnLan.enable = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Enable Wake-on-LAN for the device. + + Battery powered devices may require being connected to power. + ''; + }; }; config = { @@ -116,6 +128,10 @@ in ''} ${setNetworkServices} + + ${optionalString (cfg.wakeOnLan.enable != null) '' + systemsetup -setWakeOnNetworkAccess '${onOff cfg.wakeOnLan.enable}' &> /dev/null + ''} ''; }; diff --git a/tests/networking-wakeonlan.nix b/tests/networking-wakeonlan.nix new file mode 100644 index 00000000..745c39c9 --- /dev/null +++ b/tests/networking-wakeonlan.nix @@ -0,0 +1,10 @@ +{ config, pkgs, ... }: + +{ + networking.wakeOnLan.enable = true; + + test = '' + echo checking wake on network access settings in /activate >&2 + grep "systemsetup -setWakeOnNetworkAccess 'on'" ${config.out}/activate + ''; +} From f737259769ef4722ed956bcaaab67509b96c23cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20B=C3=B8rgesen?= Date: Sun, 19 Nov 2023 00:52:02 +0100 Subject: [PATCH 2/2] power,sleep: Add options to control restart and sleep behavior --- modules/module-list.nix | 2 + modules/power/default.nix | 47 ++++++++++++++++ modules/power/sleep.nix | 80 +++++++++++++++++++++++++++ modules/system/activation-scripts.nix | 1 + tests/power-restart.nix | 12 ++++ tests/power-sleep.nix | 16 ++++++ 6 files changed, 158 insertions(+) create mode 100644 modules/power/default.nix create mode 100644 modules/power/sleep.nix create mode 100644 tests/power-restart.nix create mode 100644 tests/power-sleep.nix diff --git a/modules/module-list.nix b/modules/module-list.nix index 6604eb92..effdff76 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -51,6 +51,8 @@ ./environment ./fonts ./launchd + ./power + ./power/sleep.nix ./services/activate-system ./services/aerospace ./services/autossh.nix diff --git a/modules/power/default.nix b/modules/power/default.nix new file mode 100644 index 00000000..a99905ff --- /dev/null +++ b/modules/power/default.nix @@ -0,0 +1,47 @@ +{ config, lib, ... }: + +let + cfg = config.power; + + types = lib.types; + + onOff = cond: if cond then "on" else "off"; +in + +{ + options = { + power.restartAfterPowerFailure = lib.mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether to restart the computer after a power failure. + ''; + }; + + power.restartAfterFreeze = lib.mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether to restart the computer after a system freeze. + ''; + }; + }; + + config = { + + system.activationScripts.power.text = '' + echo "configuring power..." >&2 + + ${lib.optionalString (cfg.restartAfterPowerFailure != null) '' + systemsetup -setRestartPowerFailure \ + '${onOff cfg.restartAfterPowerFailure}' &> /dev/null + ''} + + ${lib.optionalString (cfg.restartAfterFreeze != null) '' + systemsetup -setRestartFreeze \ + '${onOff cfg.restartAfterFreeze}' &> /dev/null + ''} + ''; + + }; +} diff --git a/modules/power/sleep.nix b/modules/power/sleep.nix new file mode 100644 index 00000000..ab5862cf --- /dev/null +++ b/modules/power/sleep.nix @@ -0,0 +1,80 @@ +{ config, lib, ... }: + +let + cfg = config.power.sleep; + + types = lib.types; + + onOff = cond: if cond then "on" else "off"; +in + +{ + options = { + power.sleep.computer = lib.mkOption { + type = types.nullOr (types.either types.ints.positive (types.enum ["never"])); + default = null; + example = "never"; + description = '' + Amount of idle time (in minutes) until the computer sleeps. + + `"never"` disables computer sleeping. + + The system might not be considered idle before connected displays sleep, as + per the `power.sleep.display` option. + ''; + }; + + power.sleep.display = lib.mkOption { + type = types.nullOr (types.either types.ints.positive (types.enum ["never"])); + default = null; + example = "never"; + description = '' + Amount of idle time (in minutes) until displays sleep. + + `"never"` disables display sleeping. + ''; + }; + + power.sleep.harddisk = lib.mkOption { + type = types.nullOr (types.either types.ints.positive (types.enum ["never"])); + default = null; + example = "never"; + description = '' + Amount of idle time (in minutes) until hard disks sleep. + + `"never"` disables hard disk sleeping. + ''; + }; + + power.sleep.allowSleepByPowerButton = lib.mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether the power button can sleep the computer. + ''; + }; + }; + + config = { + + system.activationScripts.power.text = lib.mkAfter '' + ${lib.optionalString (cfg.computer != null) '' + systemsetup -setComputerSleep '${toString cfg.computer}' &> /dev/null + ''} + + ${lib.optionalString (cfg.display != null) '' + systemsetup -setDisplaySleep '${toString cfg.display}' &> /dev/null + ''} + + ${lib.optionalString (cfg.harddisk != null) '' + systemsetup -setHardDiskSleep '${toString cfg.harddisk}' &> /dev/null + ''} + + ${lib.optionalString (cfg.allowSleepByPowerButton != null) '' + systemsetup -setAllowPowerButtonToSleepComputer \ + '${onOff cfg.allowSleepByPowerButton}' &> /dev/null + ''} + ''; + + }; +} diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix index 83251998..da8eb5c9 100644 --- a/modules/system/activation-scripts.nix +++ b/modules/system/activation-scripts.nix @@ -67,6 +67,7 @@ in ${cfg.activationScripts.nix-daemon.text} ${cfg.activationScripts.time.text} ${cfg.activationScripts.networking.text} + ${cfg.activationScripts.power.text} ${cfg.activationScripts.keyboard.text} ${cfg.activationScripts.fonts.text} ${cfg.activationScripts.nvram.text} diff --git a/tests/power-restart.nix b/tests/power-restart.nix new file mode 100644 index 00000000..ade98514 --- /dev/null +++ b/tests/power-restart.nix @@ -0,0 +1,12 @@ +{ config, pkgs, ... }: + +{ + power.restartAfterPowerFailure = true; + power.restartAfterFreeze = true; + + test = '' + echo checking restart power settings in /activate >&2 + grep "systemsetup -setRestartPowerFailure 'on'" ${config.out}/activate + grep "systemsetup -setRestartFreeze 'on'" ${config.out}/activate + ''; +} diff --git a/tests/power-sleep.nix b/tests/power-sleep.nix new file mode 100644 index 00000000..5d779a60 --- /dev/null +++ b/tests/power-sleep.nix @@ -0,0 +1,16 @@ +{ config, pkgs, ... }: + +{ + power.sleep.computer = "never"; + power.sleep.display = 15; + power.sleep.harddisk = 5; + power.sleep.allowSleepByPowerButton = false; + + test = '' + echo checking power sleep settings in /activate >&2 + grep "systemsetup -setComputerSleep 'never'" ${config.out}/activate + grep "systemsetup -setDisplaySleep '15'" ${config.out}/activate + grep "systemsetup -setHardDiskSleep '5'" ${config.out}/activate + grep "systemsetup -setAllowPowerButtonToSleepComputer 'off'" ${config.out}/activate + ''; +}