Day 1:觀念重塑 — 忘掉你熟悉的 Linux,重新認識 NixOS
介紹 NixOS 的核心哲學:聲明式配置與不可變性,帶你理解 Nix Store、Generation 等基本觀念,重塑對 Linux 系統管理的認知。
Day 1:觀念重塑 — 忘掉你熟悉的 Linux,重新認識 NixOS
系列:NixOS 30 天學習之旅
階段:第一階段 — 基礎與生存守則(Day 1 – Day 7)
核心目標:理解 Declarative 配置與 Immutability
前言:為什麼要學 NixOS?
如果你曾經在 Ubuntu 或 Arch Linux 上踩過「升級套件結果整個環境爛掉」的坑,或是花了一整個下午在 debug 某個 library 的版本衝突,那你一定能體會那種無力感。
NixOS 想解決的,正是這類問題。
它從根本上重新設計了 Linux 的套件管理與系統配置方式。不是在既有架構上打補丁,而是用一套全新的思維模型來管理整台機器 — Declarative(聲明式) 配置加上 Immutable(不可變) 的檔案系統。
這個系列的目標很單純:用 30 天的時間,從零開始理解並實際操作 NixOS。不求一步到位,但求每天都能建立一個扎實的觀念。
今天是 Day 1,我們先不急著裝系統、寫設定檔。先來一場「觀念重塑」— 理解 NixOS 和傳統 Linux 到底有什麼根本性的差異。
傳統 Linux vs NixOS:根本差異在哪?
在傳統的 Linux distribution(例如 Ubuntu、Fedora)中,你安裝軟體的方式大概是這樣的:
sudo apt install vim
這條指令背後發生了什麼事?apt 把 vim 的 binary 放進 /usr/bin/vim,把相關的 library 丟進 /usr/lib/,設定檔可能散落在 /etc/ 的各個角落。
這種做法有幾個隱含的問題:
- 全域共用路徑:所有套件共享
/usr/bin、/usr/lib,一旦某個套件升級了共用的 library,其他依賴同一版本的套件就可能壞掉。 - 狀態難以追蹤:你無法輕易知道「現在這台機器裝了哪些東西、改了哪些設定」,因為變更散佈在整個檔案系統中。
- 難以重現:想在另一台機器上建出一模一樣的環境?祝你好運。
NixOS 的回答是:徹底捨棄這套架構。
在 NixOS 上,你不會看到傳統的 /bin(除了 /bin/sh)和 /lib 目錄。所有東西都住在一個特殊的地方 — /nix/store。
Nix Store 是什麼?為什麼沒有 /bin 和 /lib?
/nix/store 是 NixOS 的核心。每一個套件、每一個 library、甚至每一個設定檔,都以一個帶有 hash prefix 的獨立路徑存放在這裡。
舉個例子,你的系統上可能同時存在兩個版本的 git:
/nix/store/abc123...-git-2.42.0/bin/git
/nix/store/xyz789...-git-2.44.0/bin/git
那串看起來像亂碼的前綴,其實是根據該套件的所有 input(source code、dependencies、build flags 等)計算出來的 cryptographic hash。只要 input 有任何一丁點不同,hash 就會不同,產生完全獨立的路徑。
這帶來幾個關鍵好處:
1. 多版本共存,互不干擾
因為每個版本都有獨立的路徑,所以不同專案可以依賴不同版本的同一個套件,完全不會衝突。
2. Reproducibility(可重現性)
同樣的 input 永遠會產出同樣的 output。今天在你的機器上 build 出來的結果,和明天在另一台機器上 build 的結果,路徑和內容會一模一樣。
3. Immutability(不可變性)
/nix/store 中的檔案在寫入後就不會被修改。要「升級」一個套件,不是去覆蓋原本的檔案,而是在 store 中建立一個全新的路徑。舊版本的檔案依然存在,直到被 garbage collection 清除。
那你可能會問:如果所有東西都在 /nix/store 裡面,系統怎麼知道要用哪個版本的程式?
答案是 symlink。NixOS 會透過一層層的 symbolic link,把目前啟用的套件串接起來,組成你實際看到的系統環境。例如:
# 你在 shell 中執行 git,實際上走的是這樣的路徑
which git
# /run/current-system/sw/bin/git → /nix/store/xyz789...-git-2.44.0/bin/git
這就是為什麼 NixOS 上沒有傳統的 /bin 或 /lib — 因為根本不需要。所有東西都透過 /nix/store 加上 symlink 來管理,乾淨、明確、可追蹤。
Declarative vs Imperative:兩種配置思維
在傳統 Linux 上,你管理系統的方式是 Imperative(指令式) 的:
# 安裝 Nginx
sudo apt install nginx
# 修改設定
sudo vim /etc/nginx/nginx.conf
# 啟動服務
sudo systemctl enable --now nginx
每一步都是一個「動作」,系統的最終狀態取決於你執行了哪些動作、以什麼順序執行。時間一久,沒有人能說清楚這台機器到底經歷了什麼。
NixOS 採用的是 Declarative(聲明式) 思維。你不是告訴系統「去做什麼」,而是告訴系統「你應該長什麼樣子」:
# /etc/nixos/configuration.nix
{ config, pkgs, ... }:
{
# 系統要安裝的套件
environment.systemPackages = with pkgs; [
vim
git
htop
];
# 啟用 Nginx 服務
services.nginx.enable = true;
# 開啟防火牆,允許 HTTP 和 HTTPS
networking.firewall.allowedTCPPorts = [ 80 443 ];
}
這份 configuration.nix 就是你整台機器的「規格書」。NixOS 會根據這份檔案,計算出系統應有的狀態,然後一次性地把系統帶到那個狀態。
這種做法的威力在於:
- 可版本控管:這就是一個純文字檔,丟進 Git 就能追蹤所有變更歷史。
- 可重現:拿同一份
configuration.nix去另一台機器上 rebuild,就能得到一模一樣的系統。 - 可審閱:新人加入團隊,看一份檔案就能理解整台 server 的配置。
套用一句話來總結:
Imperative 管理的是「過程」,Declarative 管理的是「結果」。
Generational Rollback:後悔藥內建
這是 NixOS 最讓人安心的功能之一。
每當你執行 nixos-rebuild switch(也就是「套用新的設定」),NixOS 都會建立一個新的 generation(世代)。每個 generation 就是一個完整的系統快照,包含當時的所有套件版本和設定。
# 列出所有 generation
sudo nix-env --list-generations
# 輸出大概長這樣:
# 1 2024-01-15 10:30:00
# 2 2024-01-16 14:20:00 (current)
如果你升級了某個套件結果出問題,不用慌。你可以直接回滾到上一個 generation:
# 回滾到上一個世代
sudo nixos-rebuild switch --rollback
甚至在開機畫面(GRUB bootloader)中,你就能看到每個 generation 的選項,直接選擇任何一個歷史版本開機。
這背後的原理很簡單:因為 /nix/store 是 immutable 的,舊版本的套件不會被覆蓋或刪除(除非你主動執行 garbage collection)。所以「回滾」其實只是把 symlink 指回舊的路徑而已,幾乎是瞬間完成。
這跟 Docker image 的 layer 概念有點類似,但 NixOS 是在整個作業系統層級做到這件事。
Generation 1 → /nix/store/aaa...-system/ (nginx 1.24, vim 9.0)
Generation 2 → /nix/store/bbb...-system/ (nginx 1.25, vim 9.1) ← current
Generation 3 → /nix/store/ccc...-system/ (nginx 1.25, vim 9.1, git 2.44)
想像一下:在正式環境中佈署了新版本的服務,結果出了 bug?一條指令就能安全回滾,不需要手動還原任何設定檔或重新安裝套件。這就是 Generational Rollback 帶來的安全感。
小結
今天我們建立了幾個核心觀念:
| 概念 | 說明 |
|---|---|
| Nix Store | 所有套件存放在 /nix/store,以 hash 區分版本,取代傳統的 /bin、/lib |
| Immutability | Store 中的檔案寫入後不再變更,升級是建立新路徑而非覆蓋 |
| Declarative | 用一份設定檔描述「系統應有的樣貌」,而非一步步手動操作 |
| Generational Rollback | 每次 rebuild 都會建立新的 generation,可隨時安全回滾 |
這些觀念是後續 30 天的基礎。如果現在還覺得有點抽象,別擔心 — 從明天開始我們就會實際動手操作,把這些概念變成真實的體驗。
明日預告
Day 2:安裝 NixOS — 我們將實際動手安裝 NixOS(可以用 VM 練習),體驗第一次的 configuration.nix 編輯與 nixos-rebuild switch。從零到一,讓你的第一台 NixOS 跑起來。
📚 延伸閱讀