From 7fff73e776d37a6ff3c8515c080f0ca4f05425e8 Mon Sep 17 00:00:00 2001 From: Miguel Palhas Date: Fri, 3 Jul 2026 10:50:38 +0100 Subject: [PATCH] gaming: add Steam/Sunshine stack + user-space toolkit Host (hosts/common/features/gaming/): - move steam.nix under gaming/, add gamemode + gamescope (capSysNice) - sunshine.nix: Sunshine stream host for Moonlight/Nvidia Shield (openFirewall, capSysAdmin for Wayland/KMS capture, autoStart) Home (home/common/programs/gaming.nix): - reusable custom.gaming module: Lutris, Heroic, ProtonPlus, protontricks, MangoHud, vkbasalt, vulkan-tools - NVIDIA-specific extras isolated behind custom.gaming.nvidia Wire konishi: host imports ../gaming; home enables custom.gaming with nvidia = true. Co-Authored-By: Claude Opus 4.8 (1M context) --- home/common/programs/gaming.nix | 72 ++++++++++++++++++++ home/konishi/default.nix | 6 ++ hosts/common/features/gaming/default.nix | 23 +++++++ hosts/common/features/{ => gaming}/steam.nix | 0 hosts/common/features/gaming/sunshine.nix | 24 +++++++ hosts/konishi/default.nix | 2 +- 6 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 home/common/programs/gaming.nix create mode 100644 hosts/common/features/gaming/default.nix rename hosts/common/features/{ => gaming}/steam.nix (100%) create mode 100644 hosts/common/features/gaming/sunshine.nix diff --git a/home/common/programs/gaming.nix b/home/common/programs/gaming.nix new file mode 100644 index 0000000..7351b93 --- /dev/null +++ b/home/common/programs/gaming.nix @@ -0,0 +1,72 @@ +{ + config, + lib, + pkgs, + ... +}: +# User-space gaming toolkit. Vendor-agnostic on purpose so it can be reused on +# AMD/Intel hosts — the only GPU-vendor-aware branch is `cfg.nvidia`, kept +# deliberately small. The host still owns the privileged pieces (Steam FHS +# wrapper, Sunshine, gamemode, gamescope caps) under +# hosts/common/features/gaming. +let + cfg = config.custom.gaming; +in +{ + options.custom.gaming = { + enable = lib.mkEnableOption "user-space gaming tools (launchers, Proton mgmt, MangoHud)"; + + nvidia = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Enable NVIDIA-specific extras (currently just nvtop). Keep this the only + NVIDIA-aware branch in this file so the module stays reusable on other + GPUs. NVENC streaming needs no user config — it comes from the host + NVIDIA driver. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + # NOTE: Steam itself is enabled at the host level (programs.steam) because it + # needs the FHS wrapper, udev rules and 32-bit graphics — home-manager can't + # provide those. See hosts/common/features/gaming/steam.nix. + home.packages = + with pkgs; + [ + # launchers / stores + lutris + heroic # Epic / GOG / Amazon + + # Proton / Wine compatibility tooling + protonplus # install & manage Proton-GE builds + protontricks + winetricks + + # overlays, tuning & diagnostics + goverlay # GUI to configure MangoHud / vkBasalt + vkbasalt # Vulkan post-processing layer + vulkan-tools # vulkaninfo / vkcube for sanity checks + ] + ++ lib.optionals cfg.nvidia [ + nvtopPackages.nvidia # GPU/VRAM/encoder monitor + ]; + + # In-game performance overlay (toggle with Shift+F12 by default). + programs.mangohud = { + enable = true; + settings = { + fps_limit = 0; + gpu_stats = true; + gpu_temp = true; + vram = true; + cpu_stats = true; + cpu_temp = true; + ram = true; + frametime = true; + frame_timing = true; + }; + }; + }; +} diff --git a/home/konishi/default.nix b/home/konishi/default.nix index 224e274..96cd862 100644 --- a/home/konishi/default.nix +++ b/home/konishi/default.nix @@ -12,6 +12,7 @@ ../common/programs/ethui.nix ../common/programs/3d.nix ../common/programs/godot.nix + ../common/programs/gaming.nix ../common/features/xdg.nix ../common/features/downloads-cleanup.nix ./monitors.nix @@ -28,6 +29,11 @@ cursorSize = 42; }; + custom.gaming = { + enable = true; + nvidia = true; + }; + wayland.windowManager.hyprland.settings = { exec-once = [ "$HOME/.local/bin/hyprpaper-rotate" diff --git a/hosts/common/features/gaming/default.nix b/hosts/common/features/gaming/default.nix new file mode 100644 index 0000000..3c0cd9d --- /dev/null +++ b/hosts/common/features/gaming/default.nix @@ -0,0 +1,23 @@ +{ ... }: +# Host-level gaming stack: the privileged pieces that home-manager can't +# provide. GPU-vendor-agnostic — NVIDIA/Intel/AMD drivers come from the host's +# gpu/* module. Pair this with the user-space toolkit in +# home/common/programs/gaming.nix (custom.gaming). +{ + imports = [ + ./steam.nix + ./sunshine.nix + ]; + + # Feral gamemode: games (and Lutris/Steam launch options) can request a + # CPU-governor / scheduling boost via `gamemoderun %command%`. + programs.gamemode.enable = true; + + # Micro-compositor used for tear-free, frame-paced output and upscaling. + # capSysNice lets it use realtime scheduling (`--rt`), which also helps the + # Sunshine capture path stay smooth. + programs.gamescope = { + enable = true; + capSysNice = true; + }; +} diff --git a/hosts/common/features/steam.nix b/hosts/common/features/gaming/steam.nix similarity index 100% rename from hosts/common/features/steam.nix rename to hosts/common/features/gaming/steam.nix diff --git a/hosts/common/features/gaming/sunshine.nix b/hosts/common/features/gaming/sunshine.nix new file mode 100644 index 0000000..38f818c --- /dev/null +++ b/hosts/common/features/gaming/sunshine.nix @@ -0,0 +1,24 @@ +{ ... }: +# Sunshine — self-hosted game-stream host for Moonlight clients (the NVIDIA +# Shield runs Moonlight). This is host-level because it needs root-owned bits: +# a setcap wrapper for display capture, /dev/uinput for virtual gamepad/mouse, +# and firewall ports. +# +# Encoding: on this host the RTX 4060's NVENC is picked up automatically from +# the NVIDIA driver (hosts/common/features/gpu/nvidia.nix) — no config needed. +# On an AMD/Intel host Sunshine would fall back to VAAPI; nothing here is +# NVIDIA-specific, so this module is reusable as-is. +# +# First run: open https://:47990 to set the web-UI credentials, then pair +# the Shield (enter the PIN Moonlight shows). Moonlight discovers the host via +# Sunshine's built-in mDNS, so no separate avahi service is required. +{ + services.sunshine = { + enable = true; + autoStart = true; # start with the graphical session + openFirewall = true; # 47984-48010 TCP + 47998-48010 UDP for Moonlight + # Required to capture the display under Wayland/KMS (Hyprland). Grants the + # setcap'd wrapper CAP_SYS_ADMIN. + capSysAdmin = true; + }; +} diff --git a/hosts/konishi/default.nix b/hosts/konishi/default.nix index 96364c8..bdf3713 100644 --- a/hosts/konishi/default.nix +++ b/hosts/konishi/default.nix @@ -17,7 +17,7 @@ ../common/features/bluetooth.nix ../common/features/ledger.nix ../common/features/wine.nix - ../common/features/steam.nix + ../common/features/gaming ../common/features/appimage.nix ../common/features/home ];