at 24.11-pre 6.6 kB view raw
1{ config, lib, pkgs, ... }: 2 3let 4 cfg = config.programs.steam; 5 gamescopeCfg = config.programs.gamescope; 6 7 steam-gamescope = let 8 exports = builtins.attrValues (builtins.mapAttrs (n: v: "export ${n}=${v}") cfg.gamescopeSession.env); 9 in 10 pkgs.writeShellScriptBin "steam-gamescope" '' 11 ${builtins.concatStringsSep "\n" exports} 12 gamescope --steam ${builtins.toString cfg.gamescopeSession.args} -- steam -tenfoot -pipewire-dmabuf 13 ''; 14 15 gamescopeSessionFile = 16 (pkgs.writeTextDir "share/wayland-sessions/steam.desktop" '' 17 [Desktop Entry] 18 Name=Steam 19 Comment=A digital distribution platform 20 Exec=${steam-gamescope}/bin/steam-gamescope 21 Type=Application 22 '').overrideAttrs (_: { passthru.providedSessions = [ "steam" ]; }); 23in { 24 options.programs.steam = { 25 enable = lib.mkEnableOption "steam"; 26 27 package = lib.mkOption { 28 type = lib.types.package; 29 default = pkgs.steam; 30 defaultText = lib.literalExpression "pkgs.steam"; 31 example = lib.literalExpression '' 32 pkgs.steam-small.override { 33 extraEnv = { 34 MANGOHUD = true; 35 OBS_VKCAPTURE = true; 36 RADV_TEX_ANISO = 16; 37 }; 38 extraLibraries = p: with p; [ 39 atk 40 ]; 41 } 42 ''; 43 apply = steam: steam.override (prev: { 44 extraEnv = (lib.optionalAttrs (cfg.extraCompatPackages != [ ]) { 45 STEAM_EXTRA_COMPAT_TOOLS_PATHS = lib.makeSearchPathOutput "steamcompattool" "" cfg.extraCompatPackages; 46 }) // (lib.optionalAttrs cfg.extest.enable { 47 LD_PRELOAD = "${pkgs.pkgsi686Linux.extest}/lib/libextest.so"; 48 }) // (prev.extraEnv or {}); 49 extraLibraries = pkgs: let 50 prevLibs = if prev ? extraLibraries then prev.extraLibraries pkgs else [ ]; 51 additionalLibs = with config.hardware.opengl; 52 if pkgs.stdenv.hostPlatform.is64bit 53 then [ package ] ++ extraPackages 54 else [ package32 ] ++ extraPackages32; 55 in prevLibs ++ additionalLibs; 56 } // lib.optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) 57 { 58 buildFHSEnv = pkgs.buildFHSEnv.override { 59 # use the setuid wrapped bubblewrap 60 bubblewrap = "${config.security.wrapperDir}/.."; 61 }; 62 }); 63 description = '' 64 The Steam package to use. Additional libraries are added from the system 65 configuration to ensure graphics work properly. 66 67 Use this option to customise the Steam package rather than adding your 68 custom Steam to {option}`environment.systemPackages` yourself. 69 ''; 70 }; 71 72 extraCompatPackages = lib.mkOption { 73 type = lib.types.listOf lib.types.package; 74 default = [ ]; 75 example = lib.literalExpression '' 76 with pkgs; [ 77 proton-ge-bin 78 ] 79 ''; 80 description = '' 81 Extra packages to be used as compatibility tools for Steam on Linux. Packages will be included 82 in the `STEAM_EXTRA_COMPAT_TOOLS_PATHS` environmental variable. For more information see 83 https://github.com/ValveSoftware/steam-for-linux/issues/6310. 84 85 These packages must be Steam compatibility tools that have a `steamcompattool` output. 86 ''; 87 }; 88 89 remotePlay.openFirewall = lib.mkOption { 90 type = lib.types.bool; 91 default = false; 92 description = '' 93 Open ports in the firewall for Steam Remote Play. 94 ''; 95 }; 96 97 dedicatedServer.openFirewall = lib.mkOption { 98 type = lib.types.bool; 99 default = false; 100 description = '' 101 Open ports in the firewall for Source Dedicated Server. 102 ''; 103 }; 104 105 localNetworkGameTransfers.openFirewall = lib.mkOption { 106 type = lib.types.bool; 107 default = false; 108 description = '' 109 Open ports in the firewall for Steam Local Network Game Transfers. 110 ''; 111 }; 112 113 gamescopeSession = lib.mkOption { 114 description = "Run a GameScope driven Steam session from your display-manager"; 115 default = {}; 116 type = lib.types.submodule { 117 options = { 118 enable = lib.mkEnableOption "GameScope Session"; 119 args = lib.mkOption { 120 type = lib.types.listOf lib.types.str; 121 default = [ ]; 122 description = '' 123 Arguments to be passed to GameScope for the session. 124 ''; 125 }; 126 127 env = lib.mkOption { 128 type = lib.types.attrsOf lib.types.str; 129 default = { }; 130 description = '' 131 Environmental variables to be passed to GameScope for the session. 132 ''; 133 }; 134 }; 135 }; 136 }; 137 138 extest.enable = lib.mkEnableOption '' 139 Load the extest library into Steam, to translate X11 input events to 140 uinput events (e.g. for using Steam Input on Wayland) 141 ''; 142 }; 143 144 config = lib.mkIf cfg.enable { 145 hardware.opengl = { # this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932 146 enable = true; 147 driSupport = true; 148 driSupport32Bit = true; 149 }; 150 151 security.wrappers = lib.mkIf (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) { 152 # needed or steam fails 153 bwrap = { 154 owner = "root"; 155 group = "root"; 156 source = "${pkgs.bubblewrap}/bin/bwrap"; 157 setuid = true; 158 }; 159 }; 160 161 programs.gamescope.enable = lib.mkDefault cfg.gamescopeSession.enable; 162 services.displayManager.sessionPackages = lib.mkIf cfg.gamescopeSession.enable [ gamescopeSessionFile ]; 163 164 # optionally enable 32bit pulseaudio support if pulseaudio is enabled 165 hardware.pulseaudio.support32Bit = config.hardware.pulseaudio.enable; 166 167 hardware.steam-hardware.enable = true; 168 169 environment.systemPackages = [ 170 cfg.package 171 cfg.package.run 172 ] ++ lib.optional cfg.gamescopeSession.enable steam-gamescope; 173 174 networking.firewall = lib.mkMerge [ 175 (lib.mkIf (cfg.remotePlay.openFirewall || cfg.localNetworkGameTransfers.openFirewall) { 176 allowedUDPPorts = [ 27036 ]; # Peer discovery 177 }) 178 179 (lib.mkIf cfg.remotePlay.openFirewall { 180 allowedTCPPorts = [ 27036 ]; 181 allowedUDPPortRanges = [ { from = 27031; to = 27035; } ]; 182 }) 183 184 (lib.mkIf cfg.dedicatedServer.openFirewall { 185 allowedTCPPorts = [ 27015 ]; # SRCDS Rcon port 186 allowedUDPPorts = [ 27015 ]; # Gameplay traffic 187 }) 188 189 (lib.mkIf cfg.localNetworkGameTransfers.openFirewall { 190 allowedTCPPorts = [ 27040 ]; # Data transfers 191 }) 192 ]; 193 }; 194 195 meta.maintainers = lib.teams.steam.members; 196}