本章区分 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.bottlesNVIDIA 图形扩展
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 更新 │
└─────────────────────────────────┘分层管理原则
- Nix 管理引擎:锁定可获得的软件与模块配置,同时记录构建、激活与实际 PATH/runner 选择;不承诺全部运行状态可复现。
- Steam 管理游戏兼容数据:
extraCompatPackages为 Steam 注册额外工具,不会自动把同一个 GE 包安装到 Bottles 的 runner 目录。 - Bottles 管理应用状态:每应用独立环境,记录依赖和 runner;Flatpak 更新、下载组件和 Prefix 备份仍需单独维护。
- 按实际图形栈诊断:使用匹配的 Flatpak 扩展与最小权限,不强制暴露宿主驱动目录。
- 动态工具有自己的状态:ProtonUp-Qt 等下载渠道若被采用,明确版本、路径、校验与 Nix 配置的关系,不声称它们由 flake.lock 固定。
- 系统调优凭证据:不默认打开远程防火墙,不统一提高 max_map_count/file-max,也不通过编辑受管理
/etc绕开系统配置。
sysctl 与资源限制按需配置
先查看当前值,再结合日志确认瓶颈:
cat /proc/sys/vm/max_map_count
cat /proc/sys/fs/file-max
ulimit -Sn
ulimit -Hnfs.file-max 是系统级文件句柄上限,ulimit -n 是进程相关限制,两者不是同一个参数。只有确认对应限制导致失败,才按项目证据选择目标值,并通过 Nix 模块声明;不复制超大数字作为通用推荐。
# 仅说明选项位置;validatedMapLimit 必须由实际诊断与项目配置提供。
# boot.kernel.sysctl."vm.max_map_count" = validatedMapLimit;源材料的 NixOS 25.05/24.11 范围与当前锁定输入可能不同。此次核对上游 Steam/Wine/fontconfig 模块仅确认机制与选项名称,不能替代目标 flake 的求值、构建、激活或游戏测试。
来源与核验边界#
以下参考定义相关机制与支持范围。安装、构建、激活、前缀状态与实际应用行为需要按目标环境分别核验;示例命令没有附带任何主机运行成功的结论。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。