Loading...

Day 11:Nix Search 與 Channels —— 軟體包從哪裡來?

介紹 Nixpkgs 套件庫與 Channels 機制,說明 Nix 軟體包的來源與版本管理方式。

Day 11:Nix Search 與 Channels —— 軟體包從哪裡來?

📅 NixOS 30 天學習之旅 ・ 第二階段:掌握 Nix 語言與開發環境 (Day 8 – Day 14)


前言:軟體包從哪裡來?

在前幾天的學習中,我們已經透過 nix-env -iAenvironment.systemPackages 安裝了不少軟體。但你有沒有想過:這些軟體包到底是從哪裡來的?

當你執行 nix-env -iA nixpkgs.git 的時候,Nix 去哪裡找到 Git 的 build 指令?它怎麼知道要下載哪個版本?又是誰維護這一切的?

答案就是今天的主角:NixpkgsChannels

理解這兩個概念,你才能真正掌控自己安裝的軟體版本,而不只是「裝了就好」。


Nixpkgs 是什麼?

Nixpkgs(Nix Packages)是全世界最大的軟體套件庫之一。它是一個 GitHub 上的 monorepo,裡面包含了超過 100,000 個套件的 Nix expression。

🔗 GitHub repository:https://github.com/NixOS/nixpkgs

簡單來說,Nixpkgs 就是一個巨大的 Nix 函式集合。每個套件都是一個 Nix expression,描述了如何從 source code 編譯、打包並安裝該軟體。

# 概念上,nixpkgs 就像一個巨大的 attribute set
{
  git = mkDerivation { ... };
  nodejs = mkDerivation { ... };
  firefox = mkDerivation { ... };
  # ... 超過 100,000 個套件
}

當你寫 nixpkgs.git 時,你其實就是在存取這個 attribute set 中的 git 這個 key。回想 Day 9 學過的 attribute set 語法,是不是突然覺得一切都串起來了?

Nixpkgs 的特色

特色說明
規模龐大超過 100,000 個套件,涵蓋主流程式語言、工具、桌面應用
社群驅動由全球數千名 contributor 共同維護
版本化透過 Git branch 管理不同版本的 release
可重現每個套件都有明確的 dependency tree,確保 build 結果一致

Channel 的概念

既然 Nixpkgs 是一個 Git repository,那我們要追蹤哪個 branch 呢?這就是 Channel 的用途。

Channel 就是 Nixpkgs 某個特定 branch 的「快照」,經過 CI 測試驗證後發佈出來的穩定版本。

你可以把 Channel 想成是 Ubuntu 的 apt source list,或 Homebrew 的 tap —— 它告訴 Nix「去哪裡找套件」。

常見的 Channel 種類

Channel 名稱說明適用場景
nixos-24.11穩定版(stable),約每半年 release 一次生產環境、追求穩定性
nixos-unstable滾動更新,追蹤最新套件開發環境、需要最新版本
nixos-24.11-small穩定版的精簡測試 channel,更新較快伺服器環境、不需桌面套件
nixpkgs-unstable非 NixOS 使用者的 unstable channelmacOS 或其他 Linux distro 使用 Nix

💡 stable vs unstable 怎麼選?

  • 如果你是在 production server 上跑 NixOS,選 stable(如 nixos-24.11)。
  • 如果你是開發者,想要用最新版的 Node.js、Rust 等工具,選 unstable。
  • 兩者可以並存!你可以同時訂閱多個 channel,從不同 channel 安裝不同套件。

Channel 的運作流程

GitHub nixpkgs repo

       ├── branch: nixos-24.11
       │         │
       │         ▼
       │    Hydra CI 測試
       │         │
       │         ▼ (測試通過)
       │    nixos-24.11 channel 發佈

       └── branch: nixos-unstable


            Hydra CI 測試

                 ▼ (測試通過)
            nixos-unstable channel 發佈

Hydra 是 NixOS 官方的 CI 系統。每當 Nixpkgs 的 branch 有更新,Hydra 會自動 build 並測試所有套件。只有通過測試的 commit 才會被推送到 channel 上。這就是為什麼 channel 比直接追蹤 Git branch 更可靠。


nix-channel 指令操作

查看目前的 channel

nix-channel --list

輸出範例:

nixpkgs https://nixos.org/channels/nixpkgs-unstable

如果你是 NixOS 使用者,可能會看到:

nixos https://nixos.org/channels/nixos-24.11

新增 channel

假設你目前使用 stable,想額外加入 unstable channel:

# 新增 unstable channel,並取名為 nixpkgs-unstable
nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs-unstable

# 更新 channel 資料(類似 apt update)
nix-channel --update

這裡的第二個參數 nixpkgs-unstable 是你自訂的名稱,之後可以用來指定從哪個 channel 安裝套件:

# 從 unstable channel 安裝最新版的 Node.js
nix-env -iA nixpkgs-unstable.nodejs

移除 channel

nix-channel --remove nixpkgs-unstable

更新 channel

# 更新所有 channel
nix-channel --update

# 只更新特定 channel
nix-channel --update nixpkgs

⚠️ 注意:nix-channel --update 只是下載最新的 channel 資訊,不會自動升級已安裝的套件。你需要另外執行 nix-env --upgrade 或重新 nixos-rebuild switch 才會實際更新軟體。

常用指令速查表

指令說明
nix-channel --list列出所有已訂閱的 channel
nix-channel --add <url> <name>新增 channel
nix-channel --remove <name>移除 channel
nix-channel --update更新所有 channel
nix-channel --update <name>更新指定 channel

搜尋套件的方法

知道去哪裡找套件後,接下來最常見的問題就是:「這個軟體在 Nixpkgs 裡叫什麼名字?」

方法一:search.nixos.org(推薦)

最直覺的方式就是到官方搜尋網站:

🔗 https://search.nixos.org/packages

在這裡你可以:

  • 以關鍵字搜尋套件名稱或描述
  • 查看套件的版本、license、maintainer
  • 切換不同 channel(stable / unstable)的搜尋結果
  • 直接複製安裝指令

例如搜尋 ripgrep,你會看到:

  • Package name: ripgrep
  • Version: 14.1.1(unstable 可能更新)
  • Programs provided: rg
  • Install command: nix-env -iA nixpkgs.ripgrep

這個網站還有另一個超好用的功能 —— NixOS Options 搜尋。在「Options」分頁中,你可以搜尋所有可用的 NixOS 設定選項,例如搜尋 nginx 就能看到所有 Nginx 相關的 configuration option。

方法二:nix search 指令

如果你偏好在 terminal 操作,可以使用 nix search 指令:

# 搜尋套件(需要啟用 experimental features)
nix search nixpkgs ripgrep

輸出範例:

* legacyPackages.x86_64-linux.ripgrep (14.1.1)
  A utility that combines the usability of The Silver Searcher
  with the raw speed of grep

💡 nix search 是新版 Nix CLI 的指令,需要在 ~/.config/nix/nix.conf 中啟用:

experimental-features = nix-command flakes

如果你還沒啟用新版 CLI,也可以用傳統的方式:

# 傳統搜尋方式
nix-env -qaP '.*ripgrep.*'

不過這個方法會比較慢,因為它需要 evaluate 整個 Nixpkgs。

方法三:nix-locate(按檔案搜尋)

有時候你知道指令名稱,但不知道它屬於哪個套件。這時候可以用 nix-locate

# 先安裝 nix-index
nix-env -iA nixpkgs.nix-index

# 建立索引(第一次需要,會花一點時間)
nix-index

# 搜尋提供 rg 指令的套件
nix-locate --whole-name --top-level bin/rg

輸出:

ripgrep.out    42,744 r /nix/store/...-ripgrep-14.1.1/bin/rg

這就像 Ubuntu 的 apt-file search 或 Arch 的 pkgfile 一樣實用。

搜尋方法比較

方法優點缺點
search.nixos.org直覺、資訊豐富、不需安裝需要網路
nix search快速、可 script 化需啟用 experimental features
nix-env -qaP不需額外設定速度慢
nix-locate可按檔案名搜尋需要預先建立索引

使用特定版本的套件

這是 Nix 相較於其他 package manager 最強大的功能之一:你可以輕鬆使用任何版本的套件

情境:你需要 Node.js 18,但 channel 上是 Node.js 22

在傳統的 package manager 中,這通常很麻煩。但在 Nix 的世界裡,Nixpkgs 通常會同時提供多個主要版本:

# 搜尋所有 Node.js 相關套件
nix search nixpkgs nodejs

你會發現 Nixpkgs 中有多個版本:

* legacyPackages.x86_64-linux.nodejs_18 (18.20.x)
* legacyPackages.x86_64-linux.nodejs_20 (20.18.x)
* legacyPackages.x86_64-linux.nodejs_22 (22.12.x)
* legacyPackages.x86_64-linux.nodejs (22.12.x)  # alias,指向目前預設版本

安裝特定版本非常直覺:

nix-env -iA nixpkgs.nodejs_18

或者在 NixOS configuration 中:

# /etc/nixos/configuration.nix
environment.systemPackages = with pkgs; [
  nodejs_18
  # 而不是 nodejs(預設版本)
];

使用特定 Nixpkgs commit 的套件

如果你需要的版本連 nodejs_18 都沒有涵蓋到(例如非常舊的版本),你可以固定 Nixpkgs 到某個特定的 Git commit

# 使用特定 commit 的 nixpkgs
let
  pkgs = import (fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/a3a3dda3bacf61e8a39258a0ed9c924eeca8e293.tar.gz";
    sha256 = "05fq11wg8mik4zimgvkhwvs5p7ar0ql08wbs5lhgn0m0qbqk64y";
  }) {};
in
  pkgs.nodejs

💡 如何找到特定版本的 commit?

推薦使用 NixhubNix Package Versions 這類工具,輸入套件名稱和版本號,它就會告訴你對應的 Nixpkgs commit hash。

在 nix-shell 中使用特定版本

最常見的用法是在 shell.nixnix-shell 中固定版本,確保團隊所有成員都使用一模一樣的開發環境:

# shell.nix
let
  # 固定 nixpkgs 版本
  nixpkgs = fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/nixos-24.11.tar.gz";
    sha256 = "...";
  };
  pkgs = import nixpkgs {};
in
pkgs.mkShell {
  buildInputs = [
    pkgs.nodejs_18
    pkgs.python311
    pkgs.postgresql_15
  ];
}

這就是 Nix 的 reproducibility —— 不論在誰的電腦上、什麼時候執行,都能得到完全相同的環境。


Channel vs Flakes(預告)

到目前為止,我們一直在使用 nix-channel 這個「傳統」的方式來管理 Nixpkgs 版本。但你可能已經在社群中聽過 Flakes 這個詞。

面向ChannelFlakes
版本鎖定手動管理,仰賴 nix-channel --update 的時機自動產生 flake.lock,精確鎖定每個 input 的 commit
可重現性較弱(不同時間 update 可能得到不同結果)極強(lock file 確保完全一致)
狀態管理有狀態(channel 資訊存在使用者 profile 中)無狀態(所有資訊都在 flake.nix + flake.lock
社群趨勢傳統方式,仍然穩定運作新標準,社群正積極採用中
學習曲線較低稍高,但概念更清晰

簡單來說:Channel 是「我現在訂閱了什麼版本」的全域狀態,而 Flakes 是「這個專案精確需要什麼版本」的宣告式設定。

我們會在後面的章節深入介紹 Flakes。現在只需要知道:Channel 是基礎,理解它有助於你未來學習 Flakes 時更容易掌握背後的概念。


小結

今天我們學到了:

  • Nixpkgs 是 Nix 生態系中最核心的套件庫,包含超過 100,000 個套件
  • Channel 是經過 CI 測試的 Nixpkgs 快照,分為 stable 和 unstable
  • 使用 nix-channel 指令可以管理你訂閱的 channel
  • 搜尋套件有多種方式:search.nixos.org、nix searchnix-locate
  • Nix 可以輕鬆安裝特定版本的套件,甚至固定到特定的 Nixpkgs commit
  • Flakes 是 Channel 的進化版,提供更精確的版本控制

明日預告

Day 12:Nix Derivation 深入探索

我們將揭開 Nix 最核心的抽象概念 —— Derivation。它是所有套件 build 的基礎,理解它之後,你就能真正讀懂那些 Nixpkgs 中的套件定義,甚至開始寫自己的套件。


📚 延伸閱讀