Loading...

Day 5:硬體配置 — 拆解 `hardware-configuration.nix` 與伺服器硬體管理

拆解 hardware-configuration.nix 的結構與用途,說明 NixOS 如何以聲明式方式管理硬體驅動、檔案系統與開機引導等伺服器硬體配置。

Day 5:硬體配置 — 拆解 hardware-configuration.nix 與伺服器硬體管理

🗓 系列:NixOS 30 天學習之旅
📦 階段:第一階段 — 基礎與生存守則(Day 1 – Day 7)
🎯 階段核心目標:理解 Declarative 配置與不可變性


前言:我們的場景 — Headless NixOS Server

在開始之前,先釐清我們的使用環境:

  • 遠端 NixOS server:純 CLI 環境,沒有顯示器、沒有桌面環境、沒有 GUI。所有操作都是透過 SSH 完成。
  • 本地 MacBook:使用 nix-darwin 管理,擁有 GUI 與 CLI。

這代表我們今天要討論的硬體配置,全部聚焦在 headless server 的情境。GPU 渲染、音效輸出、觸控板、藍牙配對這些桌面專屬的設定,在我們的場景裡完全用不到。我們要關心的是磁碟、檔案系統、網路介面卡、虛擬化支援、RAID 這些伺服器的核心議題。

傳統的 Linux distribution 在安裝過程中,installer 會偵測你的硬體,然後把相關設定散落在 /etc/fstab/etc/modprobe.d//etc/mkinitrd.conf 等各處。時間久了,你根本不記得哪些設定是 installer 自動產生的、哪些是你後來手動改的。

NixOS 做了一件很漂亮的事:把所有硬體相關的設定,集中在一份檔案裡hardware-configuration.nix。這份檔案在你安裝 NixOS 時自動產生,描述了磁碟分割、檔案系統掛載、需要載入的 kernel module 等等。跟 configuration.nix 拆開的原因很簡單:硬體設定是機器特定的,而 configuration.nix 是可攜的

今天我們要拆解這份檔案的每個區塊,同時深入伺服器環境常見的硬體配置。


hardware-configuration.nix 的角色與生成方式

它住在哪?

安裝完 NixOS 之後,你的 /etc/nixos/ 目錄下通常會有兩個檔案:

/etc/nixos/
├── configuration.nix             # 你的系統配置(手動編輯)
└── hardware-configuration.nix    # 硬體配置(自動產生)

它怎麼來的?

在安裝 NixOS 的過程中,installer 會執行 nixos-generate-config 這個指令。它會掃描你的硬體環境,自動產生 hardware-configuration.nix

而在 configuration.nix 中,你會看到它被 import 進來:

# /etc/nixos/configuration.nix
{ config, pkgs, ... }:

{
  imports =
    [ ./hardware-configuration.nix ];

  # ... 其他設定
}

這行 imports 就是把 hardware-configuration.nix 的內容「合併」到整份系統配置中。NixOS 的 module system 會幫你把兩份檔案的設定整合在一起,不需要你手動處理衝突。

為什麼要拆成兩個檔案?

這是一個非常實際的設計考量:

  • configuration.nix — 你的軟體配置、服務設定、使用者管理。這份可以放進 Git,帶到任何機器上使用。
  • hardware-configuration.nix — 機器特定的硬體設定。每台機器自動產生,通常不會手動編輯。

這樣的分離讓你的配置具備真正的 portability。同一份 configuration.nix 可以用在不同的 server 上,只要各自搭配對應的 hardware-configuration.nix 就好。


檔案結構詳解

讓我們來看一份典型的伺服器 hardware-configuration.nix 長什麼樣子:

# /etc/nixos/hardware-configuration.nix
# 請勿手動編輯此檔案。
# 此檔案由 nixos-generate-config 自動產生,可隨時重新生成。
{ config, lib, pkgs, modulesPath, ... }:

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

  # ─── Kernel Modules ────────────────────────────────────
  boot.initrd.availableKernelModules = [
    "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod"
  ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ "kvm-intel" ];
  boot.extraModulePackages = [ ];

  # ─── File Systems ──────────────────────────────────────
  fileSystems."/" = {
    device = "/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
    fsType = "ext4";
  };

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

  # ─── Swap ──────────────────────────────────────────────
  swapDevices =
    [ { device = "/dev/disk/by-uuid/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"; } ];

  # ─── Hardware Detection ────────────────────────────────
  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
  hardware.cpu.intel.updateMicrocode =
    lib.mkDefault config.hardware.enableRedistributableFirmware;
}

看起來不少東西,但其實結構很清晰。我們一個區塊一個區塊來拆解。

1. imports 與 modulesPath

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

modulesPath 指向 NixOS module 的根目錄。not-detected.nix 這個 module 會自動啟用 hardware.enableRedistributableFirmware,載入常見硬體需要的 firmware(例如網路卡的 firmware)。

簡單說,這行的作用是:「幫我把那些自動偵測可能遺漏的 firmware 也一起載入」

2. Kernel Modules(核心模組)

boot.initrd.availableKernelModules = [
  "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];

這裡有四個相關的設定,分別負責不同的載入階段:

設定用途
boot.initrd.availableKernelModules在 initrd(initial ramdisk)階段可以使用的模組。這些是開機過程中最早需要的 driver,例如磁碟控制器(nvmeahci)和 USB 支援(xhci_pci
boot.initrd.kernelModules在 initrd 階段強制載入的模組。與上面不同的是,available 只是「讓模組可用」,但不一定會載入;這裡列出的會直接載入
boot.kernelModules系統完整開機後才載入的模組,例如 kvm-intel(虛擬化支援)
boot.extraModulePackages額外的 kernel module 套件,用於 out-of-tree 的 driver(例如某些特殊的網卡 driver)

💡 白話解釋 initrd:initrd(initial ramdisk)是 Linux 開機時的「迷你作業系統」。在真正的 root filesystem 掛載之前,kernel 需要先有足夠的 driver 才能讀取磁碟。initrd 就是裝載這些最關鍵 driver 的地方。

3. File Systems(檔案系統掛載)

fileSystems."/" = {
  device = "/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
  fsType = "ext4";
};

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

這部分等同於傳統 Linux 的 /etc/fstab,定義了哪個 partition 掛載到哪個路徑。

幾個值得注意的細節:

  • device 使用 UUID:而不是 /dev/sda1 這種路徑。UUID 是不變的識別碼,不會因為插了一顆新硬碟就導致裝置代號跑掉。在伺服器上這尤其重要 — 你可能有多顆磁碟,裝置代號容易亂掉。
  • fsType:指定檔案系統類型。常見的有 ext4btrfsxfsvfat(EFI 分割通常用 vfat)。
  • options:掛載選項。fmask=0077dmask=0077 是安全性設定,確保 EFI 分割只有 root 能讀取。

4. Swap 設定

swapDevices =
  [ { device = "/dev/disk/by-uuid/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"; } ];

如果你有獨立的 swap partition,就會出現這個區塊。如果你偏好使用 swap file 而非 swap partition,可以改成:

swapDevices = [
  {
    device = "/swapfile";
    size = 8192;  # 單位是 MiB
  }
];

💡 伺服器的 swap 建議:在記憶體充足的 server 上,swap 通常設為 RAM 的 1–2 倍(上限通常 8–16 GB 就夠了)。如果你跑的是資料庫之類對 latency 敏感的服務,可以考慮把 vm.swappiness 調低,減少 swap 使用。

5. Platform 與 CPU Microcode

nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode =
  lib.mkDefault config.hardware.enableRedistributableFirmware;
  • nixpkgs.hostPlatform:指定目標平台架構。常見值有 x86_64-linuxaarch64-linux(ARM64)。
  • hardware.cpu.intel.updateMicrocode:啟用 Intel CPU microcode 更新。如果你用的是 AMD CPU,這行會變成 hardware.cpu.amd.updateMicrocode。Microcode 更新可以修補 CPU 層級的 bug 和安全漏洞,在伺服器上務必保持開啟

💡 關於 lib.mkDefault:這個函式設定一個「預設值」,代表你可以在 configuration.nix 中用更高優先級的值覆蓋它。這就是為什麼 hardware-configuration.nix 大量使用 mkDefault — 它提供合理的預設,但不阻止你自行調整。


伺服器磁碟與檔案系統配置

對 headless server 來說,磁碟與檔案系統的規劃是硬體配置中最核心的議題。不同的檔案系統各有優缺點,我們來看看在 NixOS 上怎麼設定。

EXT4 — 穩定可靠的萬用選擇

EXT4 是 Linux 上最成熟的檔案系統,效能穩定、工具齊全。如果你沒有特殊需求,EXT4 就是最安全的選擇。

fileSystems."/" = {
  device = "/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
  fsType = "ext4";
  options = [ "noatime" "discard" ];
};
  • noatime:不記錄每次檔案存取的時間戳記,減少磁碟寫入,提升效能。在伺服器上幾乎沒有理由不開。
  • discard:如果底層是 SSD,會自動送出 TRIM 指令,幫助 SSD 維持效能。

Btrfs — 快照與彈性空間管理

Btrfs 的殺手級功能是 subvolumesnapshot。搭配 NixOS 的 rollback 哲學,是很自然的選擇。

fileSystems."/" = {
  device = "/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
  fsType = "btrfs";
  options = [ "subvol=@" "compress=zstd" "noatime" ];
};

fileSystems."/nix" = {
  device = "/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
  fsType = "btrfs";
  options = [ "subvol=@nix" "compress=zstd" "noatime" ];
};

fileSystems."/var/log" = {
  device = "/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
  fsType = "btrfs";
  options = [ "subvol=@log" "compress=zstd" "noatime" ];
};

Btrfs 在伺服器上的實用場景:

  • 定期 snapshot:配合 services.btrbkservices.snapper 做自動排程快照
  • 透明壓縮compress=zstd 可以節省磁碟空間,對 log 目錄特別有效
  • 軟體 RAID:Btrfs 內建 RAID 0/1/10 支援(RAID 5/6 仍不建議用於 production)
# 啟用 Btrfs 自動 scrub(定期檢查資料完整性)
services.btrfs.autoScrub = {
  enable = true;
  interval = "weekly";
  fileSystems = [ "/" ];
};

ZFS — 企業級資料保護

ZFS 是資料完整性要求最高的場景的首選,內建 checksum 驗證、snapshot、compression、RAID-Z 等功能。NixOS 對 ZFS 的支援非常好。

# configuration.nix
boot.supportedFilesystems = [ "zfs" ];
boot.zfs.forceImportRoot = false;
networking.hostId = "abcd1234";  # ZFS 需要一個固定的 hostId

# ZFS 自動 scrub
services.zfs.autoScrub = {
  enable = true;
  interval = "weekly";
};

# ZFS 自動 snapshot
services.zfs.autoSnapshot = {
  enable = true;
  frequent = 4;     # 每 15 分鐘,保留最近 4 個
  hourly = 24;
  daily = 7;
  weekly = 4;
  monthly = 12;
};

ZFS pool 與 dataset 的建立通常在安裝階段用指令完成(zpool createzfs create),然後在 hardware-configuration.nix 中宣告掛載:

fileSystems."/" = {
  device = "zpool/root";
  fsType = "zfs";
};

fileSystems."/home" = {
  device = "zpool/home";
  fsType = "zfs";
};

⚠️ ZFS 與 kernel 版本:ZFS module 不在 Linux kernel 的 mainline 中,是以 out-of-tree module 的方式維護的。當 NixOS 更新 kernel 版本時,偶爾會遇到 ZFS module 尚未跟上的情況。可以透過 boot.zfs.enableUnstable 或鎖定 kernel 版本來處理。

檔案系統比較(伺服器角度)

特性EXT4BtrfsZFS
穩定性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Snapshot
壓縮✅(zstd)✅(lz4/zstd)
資料完整性驗證✅(checksum)✅(checksum)
軟體 RAID需搭配 mdadm內建 RAID 0/1/10內建 RAID-Z
記憶體需求高(建議 ≥ 8 GB)
NixOS 整合度原生原生需額外設定

伺服器核心模組管理

在 headless server 上,kernel module 的管理重點跟桌面完全不同。我們不需要 GPU driver 或音效模組,但需要確保磁碟控制器、網路卡、虛擬化等模組正確載入。

常見的伺服器 kernel module

# configuration.nix
boot.kernelModules = [
  "kvm-intel"    # Intel VT-x 虛擬化(AMD 用 "kvm-amd")
  "vfio"         # IOMMU / PCI passthrough(進階虛擬化)
  "vfio-pci"
  "br_netfilter" # Bridge 網路的 netfilter 支援(Docker/K8s 常需要)
  "ip_vs"        # IPVS(負載平衡,K8s 常用)
  "nf_conntrack" # 連線追蹤(防火牆基礎)
];

停用不需要的模組

在伺服器上,你可以明確停用不需要的模組來減少攻擊面:

# configuration.nix
boot.blacklistedKernelModules = [
  "snd_pcm"       # 音效
  "snd_hda_intel"
  "bluetooth"      # 藍牙
  "btusb"
  "pcspkr"         # PC 喇叭
];

Kernel 參數調校

伺服器常見的 kernel 參數調校:

# configuration.nix
boot.kernel.sysctl = {
  # 網路效能調校
  "net.core.somaxconn" = 65535;
  "net.ipv4.tcp_max_syn_backlog" = 65535;
  "net.core.netdev_max_backlog" = 65535;

  # 開啟 IP forwarding(如果你需要跑 Docker 或當 router)
  "net.ipv4.ip_forward" = 1;

  # 減少 swap 使用傾向(適合記憶體充足的 server)
  "vm.swappiness" = 10;

  # 增加 file descriptor 上限
  "fs.file-max" = 2097152;

  # 增加 inotify watch 上限(大量檔案的服務需要)
  "fs.inotify.max_user_watches" = 524288;
};

虛擬化支援:KVM 與 IOMMU

如果你的 server 要跑虛擬機器,KVM 是 Linux 上效能最好的虛擬化方案。NixOS 設定起來也非常直覺。

啟用 KVM

# configuration.nix
boot.kernelModules = [ "kvm-intel" ];  # AMD 用 "kvm-amd"

virtualisation.libvirtd = {
  enable = true;
  qemu = {
    swtpm.enable = true;  # TPM 模擬(某些 guest OS 需要)
    ovmf.enable = true;   # UEFI 開機支援
  };
};

IOMMU 與 PCI Passthrough

如果你需要把實體 PCI 裝置(例如一張網卡)直接 passthrough 給虛擬機器使用:

# configuration.nix

# 在 BIOS/UEFI 啟用 VT-d(Intel)或 AMD-Vi 後
boot.kernelParams = [
  "intel_iommu=on"   # AMD 用 "amd_iommu=on"
  "iommu=pt"         # passthrough mode,減少對 host 的效能影響
];

boot.kernelModules = [ "vfio" "vfio_iommu_type1" "vfio_pci" "vfio_virqfd" ];

💡 使用情境:PCI passthrough 常見於將一張 10GbE 網卡直接交給虛擬機器使用,讓 VM 獲得接近裸機的網路效能。或是把 GPU 直通給需要硬體加速的 VM(不過在 headless server 上比較少見)。


網路介面卡設定

伺服器通常有多張網路卡,甚至需要做 bonding(聚合)或 VLAN 切割。這些都可以在 NixOS 中 declaratively 設定。

多網卡基本設定

# configuration.nix
networking = {
  interfaces = {
    eno1 = {
      useDHCP = false;
      ipv4.addresses = [{
        address = "192.168.1.10";
        prefixLength = 24;
      }];
    };
    eno2 = {
      useDHCP = false;
      ipv4.addresses = [{
        address = "10.0.0.10";
        prefixLength = 24;
      }];
    };
  };
  defaultGateway = "192.168.1.1";
  nameservers = [ "1.1.1.1" "8.8.8.8" ];
};

Network Bonding(網卡聚合)

多張網卡聚合可以提供更高的頻寬或容錯能力:

# configuration.nix
networking.bonds.bond0 = {
  interfaces = [ "eno1" "eno2" ];
  driverOptions = {
    mode = "802.3ad";       # LACP 聚合(需要交換器支援)
    miimon = "100";         # 每 100ms 檢查一次連線狀態
    lacp_rate = "fast";
  };
};

networking.interfaces.bond0 = {
  useDHCP = false;
  ipv4.addresses = [{
    address = "192.168.1.10";
    prefixLength = 24;
  }];
};

常見的 bonding mode:

Mode名稱說明
balance-rrRound Robin輪流使用各網卡,增加頻寬
active-backup主備模式一張壞了自動切換,最簡單的容錯
802.3adLACP需要交換器支援,頻寬與容錯兼具

VLAN 設定

# configuration.nix
networking.vlans = {
  vlan100 = {
    id = 100;
    interface = "eno1";
  };
};

networking.interfaces.vlan100 = {
  ipv4.addresses = [{
    address = "10.100.0.10";
    prefixLength = 24;
  }];
};

網卡 Firmware

某些伺服器等級的網卡(如 Intel X710、Mellanox ConnectX 系列)需要額外的 firmware:

# configuration.nix
hardware.enableRedistributableFirmware = true;  # 載入所有可散布的 firmware
# 或者更精確地只啟用網路相關的:
hardware.firmware = with pkgs; [
  linux-firmware   # 包含大多數網卡的 firmware
];

軟體 RAID(mdadm)

如果你的伺服器沒有硬體 RAID 卡,或者你偏好使用軟體 RAID(事實上在現代 SSD 環境下,軟體 RAID 的效能通常不輸硬體 RAID),NixOS 支援透過 mdadm 設定。

# configuration.nix
boot.swraid = {
  enable = true;
  mdadmConf = ''
    MAILADDR admin@example.com
  '';
};

mdadm array 通常在安裝階段建立,然後 nixos-generate-config 會自動偵測並寫入 hardware-configuration.nix。你也可以手動宣告:

# configuration.nix
boot.initrd.availableKernelModules = [ "raid1" "raid456" ];

fileSystems."/data" = {
  device = "/dev/md/data";
  fsType = "ext4";
  options = [ "noatime" ];
};

💡 RAID 層級選擇:伺服器常用 RAID 1(mirror,適合系統碟)或 RAID 10(mirror + stripe,適合需要效能又要容錯的場景)。如果用 ZFS 或 Btrfs,它們內建了自己的 RAID 機制,不需要 mdadm。


Boot Loader 設定

伺服器的 boot loader 設定有一些特殊考量,尤其是遠端管理的需求。

GRUB 基本設定

# configuration.nix
boot.loader.grub = {
  enable = true;
  device = "/dev/sda";   # BIOS/Legacy boot
  # 或者 UEFI 模式:
  # efiSupport = true;
  # device = "nodev";
};

# UEFI 模式
boot.loader.efi.canTouchEfiVariables = true;

systemd-boot(UEFI 環境推薦)

# configuration.nix
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;

伺服器常用的 boot 設定

# configuration.nix
boot.loader.timeout = 3;  # 縮短等待時間,加速開機

# 保留較多的歷史 generation(方便遠端 rollback)
boot.loader.systemd-boot.configurationLimit = 20;

# Serial console — 遠端 IPMI/BMC 管理必備
boot.kernelParams = [
  "console=tty0"
  "console=ttyS0,115200n8"  # 同時輸出到 serial port
];
boot.loader.grub.extraConfig = ''
  serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1
  terminal_input serial console
  terminal_output serial console
'';

💡 Serial console 的重要性:在 headless server 上,如果 SSH 進不去,serial console 是你唯一的救命繩。透過 IPMI/BMC 的 SOL(Serial Over LAN)功能,你可以遠端存取 serial console,即使系統開機失敗也能看到輸出並進行除錯。


何時需要手動修改 hardware-configuration.nix

官方的建議是:大多數情況下,你不需要手動修改它。但以下情境是例外:

1. 調整掛載選項

更好的做法是在 configuration.nix 中覆蓋設定,而不是直接改 hardware-configuration.nix

# configuration.nix 中覆蓋掛載選項
fileSystems."/".options = [ "noatime" "discard" ];

2. 新增額外的磁碟掛載

當你接上一顆新的資料碟:

# configuration.nix
fileSystems."/data" = {
  device = "/dev/disk/by-uuid/zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz";
  fsType = "ext4";
  options = [ "nofail" "noatime" ];  # nofail:開機時若此磁碟不存在,不會阻止系統啟動
};

3. 手動指定 kernel module

# configuration.nix
boot.kernelModules = [ "bonding" "8021q" ];  # bonding 和 VLAN 支援

原則整理

情境建議做法
調整已有的掛載選項configuration.nix 中用 fileSystems."/".options 覆蓋
新增額外的磁碟掛載寫在 configuration.nix
新增 kernel module寫在 configuration.nix
更換硬碟後重新偵測執行 nixos-generate-config 重新產生
直接修改 hardware-configuration.nix除非你非常清楚自己在做什麼,否則盡量避免

nixos-generate-config 指令

這個指令是 hardware-configuration.nix 的幕後功臣。了解它,你就能在需要時重新產生或更新硬體配置。

基本用法

# 重新偵測硬體,產生(或覆蓋)hardware-configuration.nix
sudo nixos-generate-config

執行後,它會:

  1. 掃描 /sys/proc 等虛擬檔案系統,偵測當前載入的 kernel module
  2. 讀取已掛載的檔案系統資訊
  3. 偵測 CPU 類型與平台架構
  4. 將結果寫入 /etc/nixos/hardware-configuration.nix

⚠️ 注意:如果 /etc/nixos/configuration.nix 已經存在,它不會被覆蓋。但 hardware-configuration.nix 會被覆蓋。所以你自訂的硬體設定請務必寫在 configuration.nix 中。

常見使用情境

情境指令
安裝 NixOS 時初次產生nixos-generate-config --root /mnt
更換硬碟或重新分割後更新sudo nixos-generate-config
預覽偵測結果(不寫檔)nixos-generate-config --show-hardware-config
輸出到自訂目錄sudo nixos-generate-config --dir ~/my-config/

進階技巧:nixos-hardware

NixOS 社群維護了一個非常實用的專案:nixos-hardware

這個 repository 收錄了大量硬體平台的最佳化配置。雖然大部分是筆電和桌面硬體,但也包含了伺服器相關的 profile,例如特定 CPU 世代的最佳化和常見伺服器主機板的設定。

# 以 Intel CPU 最佳化為例
{ config, pkgs, ... }:

{
  imports = [
    ./hardware-configuration.nix
    <nixos-hardware/common/cpu/intel>
  ];

  # ... 其他設定
}

目前收錄的平台包含各世代 Intel/AMD CPU 的最佳化、Raspberry Pi、各品牌筆電等。

💡 在你的硬體沒有自動偵測到某些功能時,先到 nixos-hardware 找找看有沒有對應的 module,往往能省下大量的除錯時間。


桌面 NixOS 專屬設定(附錄)

以下設定僅適用於有桌面環境的 NixOS 機器,我們的 headless server 不需要,但為了知識完整性,簡要列出供參考。

展開桌面專屬設定

GPU 驅動:

# NVIDIA
hardware.nvidia.modesetting.enable = true;
services.xserver.videoDrivers = [ "nvidia" ];

# AMD(通常不需要額外設定,開源 driver 已內建)
hardware.graphics.enable = true;

音效(PipeWire):

security.rtkit.enable = true;
services.pipewire = {
  enable = true;
  alsa.enable = true;
  pulse.enable = true;
};

藍牙 / 觸控板 / 電源管理:

hardware.bluetooth.enable = true;
services.libinput.enable = true;
services.tlp.enable = true;  # 筆電省電

小結

今天我們從 headless server 的角度,深入拆解了 hardware-configuration.nix 並探討了伺服器環境的核心硬體配置:

概念說明
檔案分離原則configuration.nix 管軟體配置(可攜),hardware-configuration.nix 管硬體設定(機器特定)
Kernel Modules分為 initrd 階段(開機必備 driver)和系統階段(功能性 module)兩個載入時機
檔案系統選擇EXT4(穩定萬用)、Btrfs(snapshot + 壓縮)、ZFS(企業級資料保護)
虛擬化支援KVM + IOMMU 讓伺服器變身虛擬化平台
網路介面卡bonding 聚合、VLAN 切割、firmware 管理
軟體 RAIDmdadm 或直接使用 Btrfs/ZFS 內建的 RAID 機制
Boot LoaderSerial console 設定是 headless server 的救命繩
自訂硬體設定盡量寫在 configuration.nix 中覆蓋,避免直接修改 hardware-configuration.nix

經過今天的學習,你應該已經能看懂 hardware-configuration.nix 的每一行在做什麼,也知道如何為你的伺服器配置適當的檔案系統、kernel module、網路介面和虛擬化支援。


明日預告

Day 6:網路與防火牆 — 我們會深入 NixOS 的 networking module,學習如何設定靜態 IP、DNS、防火牆規則,以及如何用 declarative 的方式管理伺服器的網路安全。讓你的 NixOS server 安全地上線,也守住該守的門。

我們明天見! 🚀


📚 延伸閱讀