Loading...


什麼是 Dotfile

在 Unix 家族(Linux、macOS)裡,檔名以 . 開頭的檔案會被預設隱藏。這個慣例延伸出一整類檔案:使用者層級的工具設定檔,就叫 dotfile。

最常見的幾個例子:

  • ~/.zshrc — zsh 互動 shell 設定
  • ~/.gitconfig — Git 使用者、別名、diff tool
  • ~/.ssh/config — SSH 連線規則
  • ~/.vimrc / ~/.config/nvim/ — 編輯器設定
  • ~/.config/* — 比較新的工具改走 XDG Base Directory,集中放這裡

dotfiles的用處:透過有結構的管理並快速設定你好你的環境。zsh 一啟動就去讀 .zshrc、Git 跑任何指令前都會讀 .gitconfig。這些檔案構成你整個命令列體驗的「核心」。

~目錄裡的 dotfile


為什麼需要 Dotfiles Repo

一次用一台機器的時候,dotfile 躺在~目錄就好。但現實是:

  • 換新機:新 MacBook 到手,要重灌 shell 設定、git 別名、ssh config、偏好鍵盤速度、Dock 行為……手動設一輪半天起跳
  • 多機同步:桌機、筆電、遠端 server 三份 .zshrc 會慢慢模糊,最後沒人知道哪份是對的
  • 手動改 config 容易忘:半年後想不起為什麼某個 alias 是這樣寫

解法是把整包設定丟進 Git repo。這就是 Configuration as Code:你的偏好變成版控文字檔,跟基礎設施即程式碼(IaC)是同一個邏輯,只是 scope 落在個人工作站。

第一次建 repo 會花一兩天,但這是一次性投資。之後每次換機都是複利回報 — git clone + 一個腳本,90% 環境就回來了。

我的 repo 公開在:https://github.com/Natsusaka0505/dotfiles,歡迎 clone 或 fork。


Repo 結構

repo 結構

dotfiles/
├── shell/zsh/         # .zshenv / .zshrc / .zprofile / aliases.zsh
├── git/               # .gitconfig / .gitignore_global
├── homebrew/Brewfile  # brew / cask / tap 清單
├── ssh/config         # SSH host 設定(不含私鑰)
├── macos/defaults.sh  # Finder / Dock / 鍵盤 / 截圖等系統偏好
├── iterm2/            # color scheme等設定
├── install.sh         # 主安裝腳本
└── README.md

每個目錄對應一個關注點:shell / git / 套件 / ssh / 系統偏好 / terminal 外觀。分得夠細,但不分到讓你找不到東西。


Install 腳本拆解

整包 repo 的靈魂是 install.sh。它用最直接快速的方式解決問題 — symlink,不引入 chezmoi、stow 這類額外工具。

關鍵是這個 link() 輔助函式:

Loading...

邏輯:

  1. 檢查目標位置是否已經存在「非 symlink」的檔案 — 有就備份成 .bak
  2. 建立 symlink 指回 repo
  3. 之後 $HOME/.zshrc 實際上指向 $HOME/dotfiles/shell/zsh/.zshrc,編輯任何一邊都是改版控裡的檔案

整個腳本分成 8 段,每段一件事:

  1. 裝 Homebrew
  2. brew bundle 跑 Brewfile
  3. 裝 Oh My Zsh
  4. clone zsh-autosuggestions / zsh-syntax-highlighting / powerlevel10k
  5. 建立 symlinks(.zshenv.gitconfig.gitignore_global.ssh/config
  6. 套用 macOS defaults
  7. 裝 fzf shell 整合
  8. 下載並匯入 iTerm2 Dracula 配色

set -e 放在最上面,任何一段失敗整個腳本就停,不會留半組裝狀態。

install.sh 執行畫面


Brewfile — 一鍵裝所有套件

brew bundle 是 Homebrew 內建功能,讀 Brewfile 一次把 CLI / GUI / 字體全部裝好。

節錄:

Loading...

維護方式也一句話:舊機用 brew bundle dump --force 匯出當前狀態覆蓋檔案,新機用 brew bundle --file=... 還原。


Shell 層:zsh + Oh My Zsh + Powerlevel10k

這是整套設定的「體感來源」。核心巧思在 .zshenv

Loading...

zsh 啟動時一定會讀 ~/.zshenv(唯一無條件會讀的檔案)。只要在這裡把 ZDOTDIR 指向 repo,之後的 .zshrc.zprofilealiases.zsh 都從 repo 載入 — ~目錄只需要一個 symlink,不用每個檔案都 symlink。

.zshrc 主要做四件事:

Loading...
  • Powerlevel10k:快速、可高度客製的 prompt(p10k configure 互動式走一次)
  • zsh-autosuggestions:根據歷史灰字補全,按 → 接受
  • zsh-syntax-highlighting:指令即時上色,打錯會變紅
  • fzfCtrl+R 模糊搜歷史、Ctrl+T 模糊挑檔案

aliases.zsh 集中放別名:

Loading...

Git 設定

~/.gitconfig symlink 過來,內容包含使用者、預設分支、push / pull 行為、[alias] 區塊、以及用 VS Code 當 editor / diff tool:

Loading...

.gitignore_global 讓全域忽略 .DS_Store*.swp 這類跨 repo 雜訊,不用每個 repo 都寫一遍。


SSH 設定

~/.ssh/config 只放「client 行為」,不放私鑰

Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519

Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519

UseKeychain yes 讓 macOS 把金鑰 passphrase 存進 Keychain,重開機也不用再輸入。install.sh 會在建 symlink 後把 ~/.ssh 改成 700config 改成 600,否則 SSH 會拒絕使用。


macOS defaults.sh

macOS 的系統偏好大多可以用 defaults write 腳本化。這個檔案收了我常用的幾條:

Loading...

末尾 killall Finder Dock SystemUIServer 重啟相關 app 套用。


Secrets 策略

永遠不要 commit 的東西

  • ~/.ssh/id_*(私鑰)
  • API token、AWS credential
  • .env

這個 repo 裡只放 ssh/config(行為設定)。私鑰產生方式寫在 README 的「腳本無法自動處理的項目」:

Loading...

.gitignore 也把 install.sh 產生的 *.bak.DS_Store.zsh_history、p10k 使用者設定擋掉。


新機首日指令

Loading...

喝杯咖啡回來(可能還沒喝完XD),環境就全好了。

最後成果


未來可能的升級路線

我現在這套 bash + symlink 簡單直接,但有幾個方向可以優化:

  • chezmoi:模板引擎 + secrets 整合(1Password / age 加密)。適合多機器有差異(work vs personal)、想把 .env 也納入版控的場景
  • fish shell:自帶 autosuggestion / syntax highlight,設定比 zsh 簡單。代價是 POSIX 不相容,部分腳本要翻譯
  • starship prompt:跨 shell 的統一 prompt,Rust 寫的、秒開,取代 p10k
  • mise:一個工具取代 nvm + pyenv + goenv,專案層級 .mise.toml 自動切版本

目前還用不到這些複雜度,但 repo 長期會往這個方向演進。


完整 repo 歡迎到 https://github.com/Natsusaka0505/dotfiles。有更好的做法也請留訊息交流。