Day 2:基礎配置 —— 你的第一次 `configuration.nix` 編輯
手把手帶你編輯第一份 configuration.nix,學會安裝套件、管理使用者與開啟 SSH 服務,並透過 nixos-rebuild 讓配置生效。
Day 2:基礎配置 —— 你的第一次 configuration.nix 編輯
🗓 系列:NixOS 30 天學習之旅
📦 階段:第一階段 — 基礎與生存守則 (Day 1 – Day 7)
🎯 階段核心目標:理解 Declarative 配置與不可變性
環境說明
🖥 本系列文章的操作情境如下:
- 遠端 NixOS server(純 CLI,無 GUI、無桌面環境)——所有涉及
configuration.nix、nixos-rebuild的操作,都是透過 SSH 連線到這台 server 上執行。- 本地 MacBook(macOS + CLI/GUI)——日常開發機器,使用 nix-darwin + Home Manager 管理本地環境,不會有
/etc/nixos/configuration.nix。換句話說,當文章提到「打開
configuration.nix」或「執行sudo nixos-rebuild switch」,指的都是在遠端 NixOS server 上的操作。如果你跟我一樣是用 MacBook SSH 進 NixOS server,請先確認 SSH 連線正常再繼續。
前言
在 Day 1,我們完成了 NixOS 的安裝,初步認識了這個與眾不同的 Linux distribution。你可能已經感受到,NixOS 的世界裡沒有 apt install、沒有 yum,一切都圍繞著一個核心檔案運轉——/etc/nixos/configuration.nix。
今天,我們要正式打開這個檔案,學會三件最基本也最實用的事:
- 安裝系統套件(
environment.systemPackages) - 管理使用者帳號(
users.users) - 開啟 SSH 服務(
services.openssh)
學完這三招,你就能在 NixOS 上自由地安裝軟體、建立使用者,並確保 SSH 連線設定完善。走吧!
configuration.nix 的結構解析
SSH 進你的 NixOS server 後,用 sudo nano /etc/nixos/configuration.nix(或你偏好的 editor)打開這個檔案。你會看到類似以下的結構:
💡 MacBook 使用者提示:從你的 MacBook 終端機執行
ssh user@your-nixos-server-ip,連線成功後再進行以下操作。本地的 MacBook 上不會有這個檔案——那是 NixOS 專屬的系統配置。
# /etc/nixos/configuration.nix
{ config, pkgs, ... }:
{
imports =
[ ./hardware-configuration.nix ];
# Bootloader 設定
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# 網路
networking.hostName = "my-nixos";
# 時區
time.timeZone = "Asia/Taipei";
# 系統套件
environment.systemPackages = with pkgs; [
vim
wget
];
# 系統版本(請勿隨意更動)
system.stateVersion = "24.05";
}
幾個重點觀念
| 語法元素 | 說明 |
|---|---|
{ config, pkgs, ... }: | 這是一個 Nix function,接收 config(系統配置)和 pkgs(套件集合)作為參數 |
imports = [ ... ]; | 引入其他 .nix 檔案,hardware-configuration.nix 是安裝時自動產生的硬體設定 |
attribute = value; | Nix 的基本 key-value 設定方式,每行結尾用分號 ; |
with pkgs; [ ... ] | 語法糖,讓你在 list 裡直接寫套件名稱,不需要每個都加上 pkgs. 前綴 |
💡 小提醒:
configuration.nix本質上是一個 Nix expression,它是一個 function,回傳一個 attribute set。這也是為什麼最外層是{ ... }:搭配{ ... }的結構。
安裝系統套件(environment.systemPackages)
在 NixOS 上安裝套件,不是下指令,而是寫配置。找到 environment.systemPackages 這個區塊,把你需要的套件加進去:
environment.systemPackages = with pkgs; [
vim
wget
curl
git
htop
tmux
unzip
];
怎麼找套件名稱?
你可能會問:「我怎麼知道套件在 Nix 裡面叫什麼名字?」有幾個方法:
方法一:用 nix search 指令
# 搜尋含有 "firefox" 的套件
nix search nixpkgs firefox
方法二:到 Nix Packages 搜尋網站
前往 search.nixos.org ,在網頁上直接搜尋,這是最直覺的方式。
方法三:用 nix-env -qaP 查詢(傳統方式)
nix-env -qaP | grep firefox
💡 小提醒:
environment.systemPackages安裝的套件是 system-wide 的,所有使用者都能使用。如果你只想讓特定使用者安裝套件,Day 後面的章節會介紹home-manager,敬請期待。
使用者管理(users.users)
NixOS 的使用者管理同樣是 declarative 的。你不會用 useradd 指令來建立使用者,而是在 configuration.nix 中宣告:
users.users.james = {
isNormalUser = true;
description = "James Hsueh";
home = "/home/james";
extraGroups = [ "wheel" "networkmanager" "docker" ];
shell = pkgs.zsh;
};
各欄位說明
| 欄位 | 說明 |
|---|---|
isNormalUser | 設為 true 表示這是一般使用者(非系統帳號),會自動建立 home 目錄 |
description | 使用者的全名或描述 |
home | 指定 home 目錄路徑 |
extraGroups | 額外加入的群組。wheel 可以使用 sudo、networkmanager 可管理網路 |
shell | 指定預設 shell,注意這裡用的是 pkgs.zsh,所以要確保 zsh 有安裝 |
設定密碼
第一次建立使用者後,需要用 passwd 指令來設定密碼:
sudo passwd james
如果你想要在配置中指定 hashed password(適合自動化佈署情境),可以這樣做:
# 先產生 hashed password
mkpasswd -m sha-512
users.users.james = {
isNormalUser = true;
description = "James Hsueh";
extraGroups = [ "wheel" "networkmanager" ];
hashedPassword = "$6$xxxxxxx..."; # mkpasswd 產生的 hash
};
⚠️ 安全提醒:如果你把
configuration.nix放進 Git repository 管理(這是好習慣!),請避免直接把 hashed password 寫在裡面。後續我們會介紹sops-nix等 secrets management 方案。
如果你用了 zsh 作為 shell
別忘了同時啟用 zsh,否則系統會找不到這個 shell:
programs.zsh.enable = true;
開啟 SSH 服務(services.openssh)
SSH 是遠端管理 server 的基本功——尤其當你像我們一樣從 MacBook SSH 進 NixOS server 時,這個服務至關重要。在 NixOS 上,開啟 SSH 只需要一行:
services.openssh.enable = true;
就這樣?對,就這樣。NixOS 的 declarative 配置就是這麼簡潔。
不過,為了安全性,建議你加上更多設定:
services.openssh = {
enable = true;
settings = {
# 禁止 root 遠端登入
PermitRootLogin = "no";
# 禁止密碼登入,僅允許 SSH key
PasswordAuthentication = false;
};
};
搭配防火牆設定
NixOS 預設會開啟 firewall,所以你需要確認 SSH 的 port 有打開:
networking.firewall.allowedTCPPorts = [ 22 ];
不過好消息是,當你啟用 services.openssh.enable = true 時,NixOS 會自動在 firewall 中開啟 port 22,通常不需要手動設定。
設定 SSH Key 認證
建議搭配 SSH key 來登入,更安全也更方便:
users.users.james = {
isNormalUser = true;
description = "James Hsueh";
extraGroups = [ "wheel" "networkmanager" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3Nza... james@my-laptop"
];
};
把你的 public key 貼上去,之後就能用 SSH key 直接登入,不需要輸入密碼。
💡 MacBook 使用者提示:你的 public key 通常在本地 MacBook 的
~/.ssh/id_ed25519.pub(或id_rsa.pub)。可以在本地終端機用cat ~/.ssh/id_ed25519.pub查看,然後把內容貼到上面的authorizedKeys.keys裡。如果還沒有產生過 SSH key,先在本地執行ssh-keygen -t ed25519。
套用變更與驗證
所有修改都寫好之後,在 NixOS server 上用一個指令讓變更生效:
# 在 NixOS server 的 SSH session 中執行
sudo nixos-rebuild switch
這個指令會:
- 評估(evaluate)整份
configuration.nix - 建置(build)所有需要的套件與設定
- 切換(switch)到新的 system generation
- 啟動相關 service(如
sshd)
驗證結果
在 NixOS server 上逐一驗證:
# (在 NixOS server 上)確認套件已安裝
which git
git --version
# (在 NixOS server 上)確認使用者已建立
id james
# (在 NixOS server 上)確認 SSH 服務正在執行
systemctl status sshd
接著,回到你的 MacBook 終端機,測試 SSH 連線:
# (在本地 MacBook 上)嘗試用 SSH key 連線
ssh james@<your-nixos-server-ip>
如果能成功登入,恭喜你,SSH 配置完成!
如果出錯了怎麼辦?
不用緊張!NixOS 最強大的特性之一就是可回滾。如果新的配置有問題:
# (在 NixOS server 上)回滾到上一個 generation
sudo nixos-rebuild switch --rollback
甚至在開機時,GRUB 選單也會列出所有歷史 generation,你可以選擇舊的配置開機。這就是 NixOS immutable 設計帶來的安全感。
⚠️ SSH 使用者注意:如果你在修改 SSH 設定時不慎搞壞了連線(例如改了 port 或 key 設定),可能會導致無法遠端登入。建議在修改 SSH 相關配置時,保持至少一個 SSH session 不要斷線,先在另一個終端機視窗測試新配置是否能正常連入。
完整配置範例
把今天學到的內容整合在一起,你的 configuration.nix 大概會長這樣:
# /etc/nixos/configuration.nix
{ config, pkgs, ... }:
{
imports =
[ ./hardware-configuration.nix ];
# Bootloader
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# 網路
networking.hostName = "my-nixos";
networking.networkmanager.enable = true;
# 時區與語系
time.timeZone = "Asia/Taipei";
i18n.defaultLocale = "en_US.UTF-8";
# 系統套件
environment.systemPackages = with pkgs; [
vim
wget
curl
git
htop
tmux
unzip
];
# 使用者
users.users.james = {
isNormalUser = true;
description = "James Hsueh";
extraGroups = [ "wheel" "networkmanager" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3Nza... james@my-laptop"
];
};
# SSH
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
};
};
# 防火牆
networking.firewall.enable = true;
system.stateVersion = "24.05";
}
小結
今天我們學會了 NixOS 最核心的三項基礎配置:
| 學到了什麼 | 對應設定 |
|---|---|
| 安裝系統套件 | environment.systemPackages |
| 管理使用者 | users.users.<name> |
| 開啟 SSH 服務 | services.openssh.enable |
更重要的是,你開始體會到 NixOS 的哲學:所有系統狀態都由 configuration.nix 定義。這個檔案就像是你整台機器的 blueprint,任何時候、任何地方,只要有這個檔案,就能重建出一模一樣的系統。
這就是 declarative configuration 的威力。
明日預告
Day 3:Nix 語言入門
configuration.nix 裡那些 with、{ ... }、[ ... ] 到底是什麼?明天我們會正式認識 Nix 語言的基礎語法——變數、型別、function、let ... in,讓你讀得懂、寫得出更複雜的配置。
我們明天見! 🚀