summary refs log tree commit diff
path: root/nixos/modules/programs/gamemode.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/programs/gamemode.nix')
-rw-r--r--nixos/modules/programs/gamemode.nix98
1 files changed, 98 insertions, 0 deletions
diff --git a/nixos/modules/programs/gamemode.nix b/nixos/modules/programs/gamemode.nix
new file mode 100644
index 00000000000..a377a1619aa
--- /dev/null
+++ b/nixos/modules/programs/gamemode.nix
@@ -0,0 +1,98 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.gamemode;
+  settingsFormat = pkgs.formats.ini { };
+  configFile = settingsFormat.generate "gamemode.ini" cfg.settings;
+in
+{
+  options = {
+    programs.gamemode = {
+      enable = mkEnableOption "GameMode to optimise system performance on demand";
+
+      enableRenice = mkEnableOption "CAP_SYS_NICE on gamemoded to support lowering process niceness" // {
+        default = true;
+      };
+
+      settings = mkOption {
+        type = settingsFormat.type;
+        default = {};
+        description = ''
+          System-wide configuration for GameMode (/etc/gamemode.ini).
+          See gamemoded(8) man page for available settings.
+        '';
+        example = literalExpression ''
+          {
+            general = {
+              renice = 10;
+            };
+
+            # Warning: GPU optimisations have the potential to damage hardware
+            gpu = {
+              apply_gpu_optimisations = "accept-responsibility";
+              gpu_device = 0;
+              amd_performance_level = "high";
+            };
+
+            custom = {
+              start = "''${pkgs.libnotify}/bin/notify-send 'GameMode started'";
+              end = "''${pkgs.libnotify}/bin/notify-send 'GameMode ended'";
+            };
+          }
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment = {
+      systemPackages = [ pkgs.gamemode ];
+      etc."gamemode.ini".source = configFile;
+    };
+
+    security = {
+      polkit.enable = true;
+      wrappers = mkIf cfg.enableRenice {
+        gamemoded = {
+          owner = "root";
+          group = "root";
+          source = "${pkgs.gamemode}/bin/gamemoded";
+          capabilities = "cap_sys_nice+ep";
+        };
+      };
+    };
+
+    systemd = {
+      packages = [ pkgs.gamemode ];
+      user.services.gamemoded = {
+        # The upstream service already defines this, but doesn't get applied.
+        # See https://github.com/NixOS/nixpkgs/issues/81138
+        wantedBy = [ "default.target" ];
+
+        # Use pkexec from the security wrappers to allow users to
+        # run libexec/cpugovctl & libexec/gpuclockctl as root with
+        # the the actions defined in share/polkit-1/actions.
+        #
+        # This uses a link farm to make sure other wrapped executables
+        # aren't included in PATH.
+        environment.PATH = mkForce (pkgs.linkFarm "pkexec" [
+          {
+            name = "pkexec";
+            path = "${config.security.wrapperDir}/pkexec";
+          }
+        ]);
+
+        serviceConfig.ExecStart = mkIf cfg.enableRenice [
+          "" # Tell systemd to clear the existing ExecStart list, to prevent appending to it.
+          "${config.security.wrapperDir}/gamemoded"
+        ];
+      };
+    };
+  };
+
+  meta = {
+    maintainers = with maintainers; [ kira-bruneau ];
+  };
+}