OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 154

NixOS 中的 Wine 与游戏环境

将锁定的软件、Steam 工具注册、Flatpak 运行时与可变前缀分层管理。

所在专题Proton 游戏、部署与排错 ↗
约 13 分钟阅读开始阅读

本章区分 Nix 管理的软件/系统配置与运行时可变的前缀、下载和账号数据。示例选项需按项目锁定的 nixpkgs 核对,不能当作所有 NixOS 版本通用配置。


声明式 vs 动态:核心矛盾#

NixOS 追求可复现——锁定的输入和声明式配置可确定构建依赖与受管理的系统配置,但构建、激活和运行时状态是不同层次;存档、下载、账号和 Prefix 不会因 rebuild 自动恢复为同一状态。而 Wine/Proton 的默认行为是:

  • winetricks 从网络下载 DLL 和运行时
  • Proton-GE 从 GitHub Release 拉取新版本
  • Prefix 内的注册表修改不经过 Nix

解决策略:分清"引擎层"和"环境层"。"引擎"走 Nix 声明式,"环境"走动态管理。

引擎层 (Engine)  →  Nix 声明式  →  锁定版本与声明,另外验证构建和激活
环境层 (Prefix)  →  动态管理    →  记录安装与变更,可备份/版本化部分状态

Steam 与 Proton 的 Nix 配置#

基础模块(推荐方式)

{ config, pkgs, lib, ... }:

{
  # 允许本示例使用的 Steam unfree 包;NVIDIA 等需另按实际配置
  nixpkgs.config.allowUnfreePredicate = pkg:
    builtins.elem (lib.getName pkg) [
      "steam"
      "steam-unwrapped"
      "steam-original"
      "steam-run"
    ];

  programs.steam = {
    enable = true;
    remotePlay.openFirewall = false; # 只有明确需要 Remote Play 才单独评估开放
    localNetworkGameTransfers.openFirewall = false; # 按实际局域网传输需求配置
    protontricks.enable = true;

    # 注入 Proton-GE
    extraCompatPackages = with pkgs; [
      proton-ge-bin
    ];
  };

  # GameMode 优化调度
  programs.gamemode.enable = true;

  # 32 位字体缓存(部分游戏需要)
  fonts.fontconfig.cache32Bit = true;
}

Steam 的额外运行时包

部分游戏需要额外的系统库:

programs.steam.package = pkgs.steam.override {
  extraPkgs = pkgs': with pkgs'; [
    xorg.libXcursor
    xorg.libXi
    xorg.libXinerama
    xorg.libXScrnSaver
    libpng
    libpulseaudio
    libvorbis
    stdenv.cc.cc.lib
    libkrb5
    keyutils
  ];
};

Gamescope 微合成器

Valve 的微合成器支持 HDR、超分辨率、帧率限制:

programs.gamescope = {
  enable = true;
  capSysNice = false;  # 示例不授予该 capability;按调度需求与安全边界选择
};

programs.steam.gamescopeSession.enable = true;

Wine 引擎管理#

系统级 Wine

environment.systemPackages = with pkgs; [
  wineWowPackages.full     # 功能集合;full 不表示自动含 staging 补丁
  # wineWowPackages.stable  # 仅 stable 版
  # wineWowPackages.staging # staging 版(含额外补丁)
  winetricks               # 依赖管理(仅用于手动调试)
];

wineWowPackages 的架构与功能集合取决于锁定 nixpkgs 的打包方式;分别检查 stable、staging 与 full 的定义,不能用 full 名称推断补丁或新 WoW64 支持。Steam 的 32 位图形库需求也与普通 Wine 包不同。

环境变量按应用设定

不要全局固定 WINEPREFIX 或 WINEARCH,否则不同应用、protontricks 和管理器可能意外共用目录或使用不匹配架构。调试输出也应按场景选择,排障时全局 WINEDEBUG=-all 会隐藏证据。

# 临时针对一个独立前缀;不是 system-wide sessionVariables。
WINEPREFIX="$HOME/Games/MyTool" WINEDEBUG=+seh,+loaddll wine MyTool.exe

对固定桌面入口可在包装脚本设置单应用环境;涉及已有前缀架构迁移时先备份,按 runner 文档验证。

Bottles Flatpak 与图形运行时#

Flatpak 安装

在 NixOS 中先声明 Flatpak 服务;软件获取和应用数据仍有自己的更新/持久化范围。

services.flatpak.enable = true;

下面是服务已按项目流程激活后、用于安装应用的示例,不由本篇自动执行:

flatpak install flathub com.usebottles.bottles

NVIDIA 图形扩展

NVIDIA 需要匹配宿主内核驱动的 Flatpak 用户空间 GL 扩展。先检查宿主实际驱动、应用运行时和扩展,不能盲目添加 /run/opengl-driver、/sys 或强制宿主 ICD 路径。查看配置与列表:

flatpak info com.usebottles.bottles
flatpak info --show-permissions com.usebottles.bottles
flatpak override --user --show com.usebottles.bottles
flatpak list --runtime

宿主驱动更新与用户运行时更新需分别检查;扩展匹配后,再从 Bottle 的图形日志验证实际 GPU 和组件,而不是仅看驱动文件存在。

AMD/Intel 图形扩展

AMD/Intel 通常通过 Flatpak 运行时的 Mesa/GL 扩展提供图形库,仍需要设备权限和所需架构。不要把宿主 /usr/share/vulkan/icd.d/... 写死到沙箱环境,它可能不存在或引用不兼容库。

宿主 vulkaninfo --summary 只测宿主。Bottle 内的 DXVK/VKD3D 日志、HUD 或工具结果才描述对应运行环境;wine dxdiag 提供线索,也不能单独证明真实硬件路径与全部 Vulkan 功能。

声明式 Flatpak Override

确定权限需求后,可以把 user override 纳入 Home Manager 的用户配置,避免让 GUI 与声明式文件同时争夺管理权。以下只授权一个示例游戏目录:

xdg.dataFile."flatpak/overrides/com.usebottles.bottles".text = ''
  [Context]
  filesystems=/mnt/games;
'';

该片段用于 Home Manager 的对应用户模块,需验证 xdg.dataHome 与 Flatpak 实际读取路径。导入前检查已有 override,保留仍需要的权限;激活后用 flatpak override --user --show 核对,再实际启动应用。本篇未构建或激活这个配置,也不把声明成功等同于 GPU 可用。

三层策略与最佳实践#

┌─────────────────────────────────┐
│      引擎层 (Nix 声明式)         │
│  wineWowPackages.full           │
│  proton-ge-bin (→ Steam)        │
│  版本锁定在 Flake.lock          │
└────────────┬────────────────────┘
             │ Runner 调用
┌────────────▼────────────────────┐
│      管理层 (Bottles Flatpak)    │
│  为每个 Windows 应用创建独立 Bottle│
│  图形运行时、依赖安装、状态管理    │
│  随 Flathub 更新                │
└────────────┬────────────────────┘
             │ 紧急尝鲜
┌────────────▼────────────────────┐
│    临时层 (ProtonUp-Qt)          │
│  仅在 nixpkgs 滞后时使用        │
│  验证后等待 nixpkgs 更新        │
└─────────────────────────────────┘

分层管理原则

  1. Nix 管理引擎:锁定可获得的软件与模块配置,同时记录构建、激活与实际 PATH/runner 选择;不承诺全部运行状态可复现。
  2. Steam 管理游戏兼容数据:extraCompatPackages 为 Steam 注册额外工具,不会自动把同一个 GE 包安装到 Bottles 的 runner 目录。
  3. Bottles 管理应用状态:每应用独立环境,记录依赖和 runner;Flatpak 更新、下载组件和 Prefix 备份仍需单独维护。
  4. 按实际图形栈诊断:使用匹配的 Flatpak 扩展与最小权限,不强制暴露宿主驱动目录。
  5. 动态工具有自己的状态:ProtonUp-Qt 等下载渠道若被采用,明确版本、路径、校验与 Nix 配置的关系,不声称它们由 flake.lock 固定。
  6. 系统调优凭证据:不默认打开远程防火墙,不统一提高 max_map_count/file-max,也不通过编辑受管理 /etc 绕开系统配置。

sysctl 与资源限制按需配置

先查看当前值,再结合日志确认瓶颈:

cat /proc/sys/vm/max_map_count
cat /proc/sys/fs/file-max
ulimit -Sn
ulimit -Hn

fs.file-max 是系统级文件句柄上限,ulimit -n 是进程相关限制,两者不是同一个参数。只有确认对应限制导致失败,才按项目证据选择目标值,并通过 Nix 模块声明;不复制超大数字作为通用推荐。

# 仅说明选项位置;validatedMapLimit 必须由实际诊断与项目配置提供。
# boot.kernel.sysctl."vm.max_map_count" = validatedMapLimit;

源材料的 NixOS 25.05/24.11 范围与当前锁定输入可能不同。此次核对上游 Steam/Wine/fontconfig 模块仅确认机制与选项名称,不能替代目标 flake 的求值、构建、激活或游戏测试。

来源与核验边界#

以下参考定义相关机制与支持范围。安装、构建、激活、前缀状态与实际应用行为需要按目标环境分别核验;示例命令没有附带任何主机运行成功的结论。

参考与延伸

  1. Flatpak 图形扩展 ↗
  2. Flatpak 沙箱权限 ↗
  3. nixpkgs Steam 模块 ↗
  4. nixpkgs Wine 打包定义 ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

Proton 游戏、部署与排错

  1. 01umu、Wine 与 Proton:看懂兼容层,再选 Bottles 运行器
  2. 02Proton:游戏运行环境
  3. 03NixOS 中的 Wine 与游戏环境
  4. 04Wine 与 Proton 排错
  5. 05Wine 与 Proton 配置边界
CONTINUE READING / 下一篇Wine 与 Proton 排错

沿图形栈、前缀、媒体、音频和日志建立可以复核的故障定位流程。