typioca: 2.7.0 -> 2.8.0
[NixPkgs.git] / nixos / modules / programs / steam.nix
blob29c449c16946caa6d2129b356f4b37556df91220
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.programs.steam;
7   gamescopeCfg = config.programs.gamescope;
9   steam-gamescope = let
10     exports = builtins.attrValues (builtins.mapAttrs (n: v: "export ${n}=${v}") cfg.gamescopeSession.env);
11   in
12     pkgs.writeShellScriptBin "steam-gamescope" ''
13       ${builtins.concatStringsSep "\n" exports}
14       gamescope --steam ${toString cfg.gamescopeSession.args} -- steam -tenfoot -pipewire-dmabuf
15     '';
17   gamescopeSessionFile =
18     (pkgs.writeTextDir "share/wayland-sessions/steam.desktop" ''
19       [Desktop Entry]
20       Name=Steam
21       Comment=A digital distribution platform
22       Exec=${steam-gamescope}/bin/steam-gamescope
23       Type=Application
24     '').overrideAttrs (_: { passthru.providedSessions = [ "steam" ]; });
25 in {
26   options.programs.steam = {
27     enable = mkEnableOption (lib.mdDoc "steam");
29     package = mkOption {
30       type = types.package;
31       default = pkgs.steam;
32       defaultText = literalExpression "pkgs.steam";
33       example = literalExpression ''
34         pkgs.steam-small.override {
35           extraEnv = {
36             MANGOHUD = true;
37             OBS_VKCAPTURE = true;
38             RADV_TEX_ANISO = 16;
39           };
40           extraLibraries = p: with p; [
41             atk
42           ];
43         }
44       '';
45       apply = steam: steam.override (prev: {
46         extraLibraries = pkgs: let
47           prevLibs = if prev ? extraLibraries then prev.extraLibraries pkgs else [ ];
48           additionalLibs = with config.hardware.opengl;
49             if pkgs.stdenv.hostPlatform.is64bit
50             then [ package ] ++ extraPackages
51             else [ package32 ] ++ extraPackages32;
52         in prevLibs ++ additionalLibs;
53       } // optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice)
54       {
55         buildFHSEnv = pkgs.buildFHSEnv.override {
56           # use the setuid wrapped bubblewrap
57           bubblewrap = "${config.security.wrapperDir}/..";
58         };
59       });
60       description = lib.mdDoc ''
61         The Steam package to use. Additional libraries are added from the system
62         configuration to ensure graphics work properly.
64         Use this option to customise the Steam package rather than adding your
65         custom Steam to {option}`environment.systemPackages` yourself.
66       '';
67     };
69     remotePlay.openFirewall = mkOption {
70       type = types.bool;
71       default = false;
72       description = lib.mdDoc ''
73         Open ports in the firewall for Steam Remote Play.
74       '';
75     };
77     dedicatedServer.openFirewall = mkOption {
78       type = types.bool;
79       default = false;
80       description = lib.mdDoc ''
81         Open ports in the firewall for Source Dedicated Server.
82       '';
83     };
85     gamescopeSession = mkOption {
86       description = mdDoc "Run a GameScope driven Steam session from your display-manager";
87       default = {};
88       type = types.submodule {
89         options = {
90           enable = mkEnableOption (mdDoc "GameScope Session");
91           args = mkOption {
92             type = types.listOf types.str;
93             default = [ ];
94             description = mdDoc ''
95               Arguments to be passed to GameScope for the session.
96             '';
97           };
99           env = mkOption {
100             type = types.attrsOf types.str;
101             default = { };
102             description = mdDoc ''
103               Environmental variables to be passed to GameScope for the session.
104             '';
105           };
106         };
107       };
108     };
109   };
111   config = mkIf cfg.enable {
112     hardware.opengl = { # this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932
113       enable = true;
114       driSupport = true;
115       driSupport32Bit = true;
116     };
118     security.wrappers = mkIf (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) {
119       # needed or steam fails
120       bwrap = {
121         owner = "root";
122         group = "root";
123         source = "${pkgs.bubblewrap}/bin/bwrap";
124         setuid = true;
125       };
126     };
128     programs.gamescope.enable = mkDefault cfg.gamescopeSession.enable;
129     services.xserver.displayManager.sessionPackages = mkIf cfg.gamescopeSession.enable [ gamescopeSessionFile ];
131     # optionally enable 32bit pulseaudio support if pulseaudio is enabled
132     hardware.pulseaudio.support32Bit = config.hardware.pulseaudio.enable;
134     hardware.steam-hardware.enable = true;
136     environment.systemPackages = [
137       cfg.package
138       cfg.package.run
139     ] ++ lib.optional cfg.gamescopeSession.enable steam-gamescope;
141     networking.firewall = lib.mkMerge [
142       (mkIf cfg.remotePlay.openFirewall {
143         allowedTCPPorts = [ 27036 ];
144         allowedUDPPortRanges = [ { from = 27031; to = 27036; } ];
145       })
147       (mkIf cfg.dedicatedServer.openFirewall {
148         allowedTCPPorts = [ 27015 ]; # SRCDS Rcon port
149         allowedUDPPorts = [ 27015 ]; # Gameplay traffic
150       })
151     ];
152   };
154   meta.maintainers = with maintainers; [ mkg20001 ];