about summary refs log tree commit diff
path: root/nixos/modules/programs/steam.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/programs/steam.nix')
-rw-r--r--nixos/modules/programs/steam.nix111
1 files changed, 73 insertions, 38 deletions
diff --git a/nixos/modules/programs/steam.nix b/nixos/modules/programs/steam.nix
index 58aa0aa25b082..5138588dbd3e5 100644
--- a/nixos/modules/programs/steam.nix
+++ b/nixos/modules/programs/steam.nix
@@ -1,17 +1,17 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.steam;
   gamescopeCfg = config.programs.gamescope;
 
+  extraCompatPaths = lib.makeSearchPathOutput "steamcompattool" "" cfg.extraCompatPackages;
+
   steam-gamescope = let
     exports = builtins.attrValues (builtins.mapAttrs (n: v: "export ${n}=${v}") cfg.gamescopeSession.env);
   in
     pkgs.writeShellScriptBin "steam-gamescope" ''
       ${builtins.concatStringsSep "\n" exports}
-      gamescope --steam ${toString cfg.gamescopeSession.args} -- steam -tenfoot -pipewire-dmabuf
+      gamescope --steam ${builtins.toString cfg.gamescopeSession.args} -- steam -tenfoot -pipewire-dmabuf
     '';
 
   gamescopeSessionFile =
@@ -24,13 +24,13 @@ let
     '').overrideAttrs (_: { passthru.providedSessions = [ "steam" ]; });
 in {
   options.programs.steam = {
-    enable = mkEnableOption "steam";
+    enable = lib.mkEnableOption "steam";
 
-    package = mkOption {
-      type = types.package;
+    package = lib.mkOption {
+      type = lib.types.package;
       default = pkgs.steam;
-      defaultText = literalExpression "pkgs.steam";
-      example = literalExpression ''
+      defaultText = lib.literalExpression "pkgs.steam";
+      example = lib.literalExpression ''
         pkgs.steam-small.override {
           extraEnv = {
             MANGOHUD = true;
@@ -44,8 +44,8 @@ in {
       '';
       apply = steam: steam.override (prev: {
         extraEnv = (lib.optionalAttrs (cfg.extraCompatPackages != [ ]) {
-          STEAM_EXTRA_COMPAT_TOOLS_PATHS = makeSearchPathOutput "steamcompattool" "" cfg.extraCompatPackages;
-        }) // (optionalAttrs cfg.extest.enable {
+          STEAM_EXTRA_COMPAT_TOOLS_PATHS = extraCompatPaths;
+        }) // (lib.optionalAttrs cfg.extest.enable {
           LD_PRELOAD = "${pkgs.pkgsi686Linux.extest}/lib/libextest.so";
         }) // (prev.extraEnv or {});
         extraLibraries = pkgs: let
@@ -55,7 +55,8 @@ in {
             then [ package ] ++ extraPackages
             else [ package32 ] ++ extraPackages32;
         in prevLibs ++ additionalLibs;
-      } // optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice)
+        extraPkgs = p: (cfg.extraPackages ++ lib.optionals (prev ? extraPkgs) (prev.extraPkgs p));
+      } // lib.optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice)
       {
         buildFHSEnv = pkgs.buildFHSEnv.override {
           # use the setuid wrapped bubblewrap
@@ -71,10 +72,23 @@ in {
       '';
     };
 
-    extraCompatPackages = mkOption {
-      type = types.listOf types.package;
+    extraPackages = lib.mkOption {
+      type = lib.types.listOf lib.types.package;
+      default = [ ];
+      example = lib.literalExpression ''
+        with pkgs; [
+          gamescope
+        ]
+      '';
+      description = ''
+        Additional packages to add to the Steam environment.
+      '';
+    };
+
+    extraCompatPackages = lib.mkOption {
+      type = lib.types.listOf lib.types.package;
       default = [ ];
-      example = literalExpression ''
+      example = lib.literalExpression ''
         with pkgs; [
           proton-ge-bin
         ]
@@ -88,46 +102,59 @@ in {
       '';
     };
 
-    remotePlay.openFirewall = mkOption {
-      type = types.bool;
+    fontPackages = lib.mkOption {
+      type = lib.types.listOf lib.types.package;
+      # `fonts.packages` is a list of paths now, filter out which are not packages
+      default = builtins.filter lib.types.package.check config.fonts.packages;
+      defaultText = lib.literalExpression "builtins.filter lib.types.package.check config.fonts.packages";
+      example = lib.literalExpression "with pkgs; [ source-han-sans ]";
+      description = ''
+        Font packages to use in Steam.
+
+        Defaults to system fonts, but could be overridden to use other fonts — useful for users who would like to customize CJK fonts used in Steam. According to the [upstream issue](https://github.com/ValveSoftware/steam-for-linux/issues/10422#issuecomment-1944396010), Steam only follows the per-user fontconfig configuration.
+      '';
+    };
+
+    remotePlay.openFirewall = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Open ports in the firewall for Steam Remote Play.
       '';
     };
 
-    dedicatedServer.openFirewall = mkOption {
-      type = types.bool;
+    dedicatedServer.openFirewall = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Open ports in the firewall for Source Dedicated Server.
       '';
     };
 
-    localNetworkGameTransfers.openFirewall = mkOption {
-      type = types.bool;
+    localNetworkGameTransfers.openFirewall = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Open ports in the firewall for Steam Local Network Game Transfers.
       '';
     };
 
-    gamescopeSession = mkOption {
+    gamescopeSession = lib.mkOption {
       description = "Run a GameScope driven Steam session from your display-manager";
       default = {};
-      type = types.submodule {
+      type = lib.types.submodule {
         options = {
-          enable = mkEnableOption "GameScope Session";
-          args = mkOption {
-            type = types.listOf types.str;
+          enable = lib.mkEnableOption "GameScope Session";
+          args = lib.mkOption {
+            type = lib.types.listOf lib.types.str;
             default = [ ];
             description = ''
               Arguments to be passed to GameScope for the session.
             '';
           };
 
-          env = mkOption {
-            type = types.attrsOf types.str;
+          env = lib.mkOption {
+            type = lib.types.attrsOf lib.types.str;
             default = { };
             description = ''
               Environmental variables to be passed to GameScope for the session.
@@ -137,20 +164,25 @@ in {
       };
     };
 
-    extest.enable = mkEnableOption ''
+    extest.enable = lib.mkEnableOption ''
       Load the extest library into Steam, to translate X11 input events to
       uinput events (e.g. for using Steam Input on Wayland)
     '';
+
+    protontricks = {
+      enable = lib.mkEnableOption "protontricks, a simple wrapper for running Winetricks commands for Proton-enabled games";
+      package = lib.mkPackageOption pkgs "protontricks" { };
+    };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     hardware.opengl = { # this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932
       enable = true;
       driSupport = true;
       driSupport32Bit = true;
     };
 
-    security.wrappers = mkIf (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) {
+    security.wrappers = lib.mkIf (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) {
       # needed or steam fails
       bwrap = {
         owner = "root";
@@ -160,8 +192,10 @@ in {
       };
     };
 
-    programs.gamescope.enable = mkDefault cfg.gamescopeSession.enable;
-    services.displayManager.sessionPackages = mkIf cfg.gamescopeSession.enable [ gamescopeSessionFile ];
+    programs.steam.extraPackages = cfg.fontPackages;
+
+    programs.gamescope.enable = lib.mkDefault cfg.gamescopeSession.enable;
+    services.displayManager.sessionPackages = lib.mkIf cfg.gamescopeSession.enable [ gamescopeSessionFile ];
 
     # optionally enable 32bit pulseaudio support if pulseaudio is enabled
     hardware.pulseaudio.support32Bit = config.hardware.pulseaudio.enable;
@@ -171,28 +205,29 @@ in {
     environment.systemPackages = [
       cfg.package
       cfg.package.run
-    ] ++ lib.optional cfg.gamescopeSession.enable steam-gamescope;
+    ] ++ lib.optional cfg.gamescopeSession.enable steam-gamescope
+    ++ lib.optional cfg.protontricks.enable (cfg.protontricks.package.override { inherit extraCompatPaths; });
 
     networking.firewall = lib.mkMerge [
-      (mkIf (cfg.remotePlay.openFirewall || cfg.localNetworkGameTransfers.openFirewall) {
+      (lib.mkIf (cfg.remotePlay.openFirewall || cfg.localNetworkGameTransfers.openFirewall) {
         allowedUDPPorts = [ 27036 ]; # Peer discovery
       })
 
-      (mkIf cfg.remotePlay.openFirewall {
+      (lib.mkIf cfg.remotePlay.openFirewall {
         allowedTCPPorts = [ 27036 ];
         allowedUDPPortRanges = [ { from = 27031; to = 27035; } ];
       })
 
-      (mkIf cfg.dedicatedServer.openFirewall {
+      (lib.mkIf cfg.dedicatedServer.openFirewall {
         allowedTCPPorts = [ 27015 ]; # SRCDS Rcon port
         allowedUDPPorts = [ 27015 ]; # Gameplay traffic
       })
 
-      (mkIf cfg.localNetworkGameTransfers.openFirewall {
+      (lib.mkIf cfg.localNetworkGameTransfers.openFirewall {
         allowedTCPPorts = [ 27040 ]; # Data transfers
       })
     ];
   };
 
-  meta.maintainers = teams.steam;
+  meta.maintainers = lib.teams.steam.members;
 }