初始配置

configuration.nix

# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).

{ config, pkgs, ... }:

{
  imports =
    [
      ./hardware-configuration.nix      # Include the results of the hardware scan.
    ];

  # Use the systemd-boot EFI boot loader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # linuxPackages_6_18 = 6.18.54 LTS(7.2.8 上 nvidia-drm 编译失败,故不用)
  boot.kernelPackages = pkgs.linuxPackages_6_18;
  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";

  # Set your time zone.
  time.timeZone = "Asia/Shanghai";

  # Select internationalisation properties.
  i18n.defaultLocale = "zh_CN.UTF-8";

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "zh_CN.UTF-8";
    LC_IDENTIFICATION = "zh_CN.UTF-8";
    LC_MEASUREMENT = "zh_CN.UTF-8";
    LC_MONETARY = "zh_CN.UTF-8";
    LC_NAME = "zh_CN.UTF-8";
    LC_NUMERIC = "zh_CN.UTF-8";
    LC_PAPER = "zh_CN.UTF-8";
    LC_TELEPHONE = "zh_CN.UTF-8";
    LC_TIME = "zh_CN.UTF-8";
  };

  # Enable the X11 windowing system.
  # You can disable this if you're only using the Wayland session.
  services.xserver.enable = true;

  # Enable the KDE Plasma Desktop Environment.
  services.displayManager.sddm.enable = true;
  # greeter 用 X11:实测 KWin-Wayland 的 DRM 后端在外接屏(DP-7,2560x1440)接着时会
  # 反复报 "kwin_wayland_drm: Atomic modeset test failed! 设备上没有空间"(ENOSPC),
  # 于是 greeter 什么都画不出来 → 开机黑屏;拔掉外接屏后输出集变小、原子提交能过,登录界面才出现。
  # 本机登录后的会话本来就是 X11(startplasma-x11),greeter 没必要用 Wayland。
  # 此项只影响 greeter 的显示服务器;登录时仍可正常选择 Plasma (Wayland) 会话。
  services.displayManager.sddm.wayland.enable = false;
  services.desktopManager.plasma6.enable = true;

  # Configure keymap in X11
  services.xserver.xkb = {
    layout = "cn";
    variant = "";
  };

  # Enable CUPS to print documents.
  services.printing.enable = true;

  # Enable sound with pipewire.
  services.pulseaudio.enable = false;
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    # If you want to use JACK applications, uncomment this
    # jack.enable = true;
  };

  # Enable touchpad support (enabled default in most desktopManager).
  # services.libinput.enable = true;


  # Some programs need SUID wrappers, can be configured further or are
  # started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  # services.openssh.enable = true;

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  # networking.firewall.enable = false;

  # Copy the NixOS configuration file and link it from the resulting system
  # (/run/current-system/configuration.nix). This is useful in case you
  # accidentally delete configuration.nix.
  # system.copySystemConfiguration = true;

  # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
  system.stateVersion = "26.05"; # Did you read the comment?

  # ─────────────── network ───────────────
  networking.hostName = "max2-nixos"; # Define your hostname.
  networking.proxy.default = "http://127.0.0.1:7890";
  networking.proxy.noProxy = "127.0.0.1,localhost,192.*,172.*,internal.domain,*.cn";
  networking.networkmanager.enable = true;

  # ─────────────── user ───────────────
  users.users."cat" = {
    isNormalUser = true;
    description = "cat";
    extraGroups = [ "networkmanager" "wheel" "docker"];     # docker: exec
    packages = with pkgs; [
      kdePackages.kate
    #  thunderbird
    ];
  };
  users.users.cat.linger = true;                            # hermes:网关/定时任务需要 user systemd 常驻

  # ─────────────── packages ───────────────
  nixpkgs.config.allowUnfree = true;
  environment.systemPackages = with pkgs; [ git curl docker-compose gcc gnumake python3 pkg-config usbutils efibootmgr];  # efibootmgr:手动调 UEFI 启动顺序
  programs.firefox.enable = true;
  programs.vim.enable = true;                               # vim: enable
  environment.shellAliases = {
    vi = "vim";                                             # vim: alias
    d = "docker compose";                                   # docker: alias
  };
  # ─────────────── software ───────────────
  nix.settings.experimental-features = [ "nix-command" "flakes" ]; 	# hermes: flake(nix run / 模块)开启
  programs.nix-ld.enable = true;                            # hermes: install uv depend
  programs.nix-ld.libraries = pkgs.lib.mkAfter (with pkgs; [ glib nss nspr dbus atk at-spi2-atk at-spi2-core cups cairo gtk3 pango libglvnd libgbm libdrm expat libxcb libxkbcommon alsa-lib libsecret libXtst libx11 libxcomposite libxdamage libxext libxfixes libxrandr libxcursor libxi ]);     # Hermes: Desktop depend: mkAfter 追加
  environment.localBinInPath = true;                        # hermes: 让 ~/.local/bin 进 PATH CLI 包装器
  virtualisation.docker = {
    enable = true;                                          # docker:必须保留,Rootless 模式也需要此选项
    rootless = {
      enable = true;
      setSocketVariable = true;                             # docker:自动将 DOCKER_HOST 环境变量指向 Rootless 实例[reference:1]
    };
  };

  # ─────────────── input ───────────────
  i18n.inputMethod = {
    enable = true;
    type = "fcitx5";
    fcitx5 = {
      waylandFrontend = false;                              # rime:本机为X11,会卡漏,所以关闭
      addons = with pkgs; [
        qt6Packages.fcitx5-chinese-addons                   # rime:提供拼音、双拼等基础中文输入
        (fcitx5-rime.override {
          librime = librime.override {
            plugins = [ (librime-lua.override { lua = lua5_4; }) librime-octagram ];
          };
        })
        fcitx5-gtk                                          # rime:提供 GTK 程序支持
        qt6Packages.fcitx5-configtool                       # rime:GUI 配置工具
      ];
    };
  };
}

hardware-configuration.nix

# Do not modify this file!  It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations.  Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:

let
  # NVIDIA 驱动包(钉死具体版本,与 nixpkgs stable 同源已核验):供内核模块与 nvidia-smi 使用
  nvidiaPkg = config.boot.kernelPackages.nvidiaPackages.mkDriver {
      version = "595.71.05";
      sha256_64bit = "sha256-NiA7iWC35JyKQva6H1hjzeNKBek9KyS3mK8G3YRva4I=";
      sha256_aarch64 = "sha256-XzKloS00dFKTd4ATWkTIhm9eG/OzR/Sim6MboNZWPu8=";
      openSha256 = "sha256-Lfz71QWKM6x/jD2B22SWpUi7/og30HRlXg1kL3EWzEw=";
      settingsSha256 = "sha256-mXnf3jyvznfB3OfKd657rxv0rYHQb/dX/Riw/+N9EKU=";
      persistencedSha256 = "sha256-Z/6IvEEa/XfZ5F5qoSIPvXJLGtscYVqjFxHZaN/M2Ts=";
    };
in

{
  imports =
    [ (modulesPath + "/installer/scan/not-detected.nix")
    ];

  boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usbhid" "usb_storage" "sd_mod" "sdhci_pci" ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ "kvm-amd" ];
  boot.extraModulePackages = [ ];

  fileSystems."/" =
    { device = "/dev/disk/by-uuid/a4c3948c-a7d9-4cb1-b080-5ce6a9b0c9fa";
      fsType = "ext4";
    };

  fileSystems."/boot" =
    { device = "/dev/disk/by-uuid/CAE3-699F";
      fsType = "vfat";
      options = [ "fmask=0077" "dmask=0077" ];
    };

  swapDevices = [ ];

  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
  hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;

  # ═════════════════════ 无线 Intel AX210 ═════════════════════
  # iwlwifi(内核内)+ linux-firmware 20260916 / 固件 ty-a0-gf-a0-89
  boot.kernelParams = [ "cfg80211.ieee80211_regdom=CN" ];   # 管制域 CN:否则 5G 全段 no-IR,只能扫到不能关联
  boot.extraModprobeConfig = "options iwlwifi power_save=0 bt_coex_active=0 disable_11ax=1 disable_11ac=1";
  # disable_11ac=1 = 5G 崩因(11ac/VHT 通路固件 assert,每 ~11s 一次 SW reset)的缓解;代价:5G 退回 11n

  # ═════════════════════ 蓝牙 Intel AX210 ═════════════════════
  # btusb(内核内)+ bluez;hardware.bluetooth.enable 默认 false
  hardware.bluetooth.enable = true;

  # ═════════════════════ 雷雳 Thunderbolt ═════════════════════
  # thunderbolt(内核内)+ bolt;本机安全等级 user,不装 bolt 设备不上 PCIe(eGPU 必需)
  services.hardware.bolt.enable = true;

  # ═════════════════════ eGPU NVIDIA RTX 4060 ═════════════════════
  # nvidia 595.71.05(open 模块,钉版 + 5 个哈希)+ amdgpu 25.0.0(核显)
  # 第一屏必须用 amdgpu 而非 modesetting:modesetting 的 Device 不带 BusID,X 会去抓 PCI 首块显示卡(01:00.0 = 4060),
  # 驱动 nvidia 卡失败 → "modeset(G0): Failed to create pixmap" → "failed to create screen resources" → X 退出
  services.xserver.videoDrivers = [ "amdgpu" "nvidia" ];
  hardware.nvidia = {
    open = true;
    modesetting.enable = true;                 # nvidia_drm.modeset=1,PRIME 输出必需
    nvidiaSettings = true;
    powerManagement.enable = false;            # eGPU 热插拔,不做运行时电源管理
    package = nvidiaPkg;
    prime = {
      offload.enable = true;                   # 核显负责输出,4060 负责渲染与额外输出
      reverseSync.enable = true;               # 关键:4060 上的外接输出以 reverse PRIME(GPU screen NVIDIA-G0) 接进核显主屏
      amdgpuBusId = "PCI:102:0:0";
      nvidiaBusId = "PCI:1:0:0";
    };
  };
  environment.systemPackages = [ nvidiaPkg pkgs.fprintd ];   # nvidia-smi / fprintd-enroll 等 CLI

  # ═════════════════════ 指纹 Chipsailing CS9711(USB 2541:9711)═════════════════════
  # libfprint 1.94.10 + 社区 fork archeYR/libfprint-CS9711 rev 02b285c(上游无此芯片驱动)
  nixpkgs.overlays = [
    (final: prev: {
      libfprint = prev.libfprint.overrideAttrs (old: {
        src = prev.fetchFromGitHub {
          owner = "archeYR";
          repo = "libfprint-CS9711";
          rev = "02b285c9703c38d308fbe47a3c566ef1e7f883ca";
          hash = "sha256-QGrBNqbRNqLZIURI66xkenlQamNW+DQU4WS+CLN4zM8=";
        };
        # fork 除 CS9711 驱动外还带 sigfm 匹配器,meson 里 opencv4/doctest 均 required: true
        buildInputs = old.buildInputs ++ [ prev.opencv4 prev.doctest ];
      });
    })
  ];
  services.fprintd.enable = true;                  # fprintd 使用被覆盖的 libfprint
  # 两处 fprintAuth 需要 mkForce:nixpkgs/KDE 模块已给出定义,普通赋值会冲突
  security.pam.services.sddm.fprintAuth = lib.mkForce true;    # 登录界面可用指纹
  security.pam.services.kde.fprintAuth = lib.mkForce true;     # 桌面锁屏解锁可用指纹

  # ═════════════════════ 免配置即可用 ═════════════════════
  # amdgpu / NPU amdxdna / k10temp / snd_hda_intel / nvme ×2 / sdhc / 触摸板 / 摄像头 / gpd_fan
}