Skip to main content

SSH Key 管理

產生 SSH Key​

首先輸入指令來產生 key:

ssh-keygen

接著會詢問產生的 SSH key 要存放的位置。

預設為 /home/username/.ssh/id_rsa,如果不同伺服器會使用不同的 key,則改變 key 的位置(例如:/home/username/.ssh/id_rsa_ubuntu)。

id_rsa		id_rsa.pub <= 把這個東西打開	known_hosts
cat id_rsa.pub

再把公 key copy 下來。

參考文章


macOS:不用一直輸入 passphrase​

適用情境:你用 git pull、git push 等指令時,Terminal 一直問:

Enter passphrase for key '/Users/你的帳號/.ssh/id_ed25519_xxx':

這代表私鑰有設 passphrase(這是好事,丟了 key 別人也不能直接用),但 macOS 預設不會把 passphrase 長期記住,重開機或新開 session 後又會再問一次。

解法是把 passphrase 存進 Apple Keychain,之後由系統自動解鎖,不必每次手動輸入。

第一步:設定 ~/.ssh/config​

編輯(或新建)~/.ssh/config,在檔案最上方加入:

Host *
AddKeysToAgent yes
UseKeychain yes
選項作用
UseKeychain yes告訴 SSH 從 macOS Keychain 讀取 / 儲存 passphrase
AddKeysToAgent yes第一次使用時自動把 key 加進 ssh-agent
tip

Host * 這段建議放在檔案最上面。SSH 由上往下讀取,較具體的 Host 規則通常寫在後面覆寫。

若你會把同一份 config 同步到 Linux,Linux 不認識 UseKeychain,可在前面加:

Host *
IgnoreUnknown UseKeychain,AddKeysToAgent
AddKeysToAgent yes
UseKeychain yes

第二步:把 key 存進 Keychain(只需做一次)​

對每一把有 passphrase 的私鑰執行(macOS Monterey 12+):

ssh-add --apple-use-keychain ~/.ssh/id_ed25519_xxx

輸入最後一次 passphrase。成功後,macOS 會把 passphrase 存進 Keychain;之後 git pull / git push / ssh 就不會再一直問。

多把 key 就各執行一次:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519_personal
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_company
caution

請使用系統內建的 /usr/bin/ssh-add。若你用 Homebrew 安裝了 OpenSSH,ssh-add 可能指向 Homebrew 版本,不支援 --apple-use-keychain。不確定時用完整路徑:

/usr/bin/ssh-add --apple-use-keychain ~/.ssh/id_ed25519_xxx

第三步(可選):開新 Terminal 自動從 Keychain 載入​

若重開機或新開 shell 後又偶發被問 passphrase,可在 ~/.zshrc 加上:

ssh-add --apple-load-keychain -q 2>/dev/null

-q 可抑制每次開 Terminal 印出 Identity added: ... 的訊息。

驗證​

# 確認 key 已在 agent 裡
ssh-add -l

# 測 GitLab / GitHub(不應再問 passphrase)
ssh -T git@gitlab.com -i ~/.ssh/id_ed25519_xxx -o IdentitiesOnly=yes
ssh -T git@github.com -i ~/.ssh/id_ed25519_xxx -o IdentitiesOnly=yes

預期不會再出現 Enter passphrase for key ...;若遠端已登記公鑰,會看到歡迎訊息。

和「多把 key」一起用時​

Keychain 只解決「不用一直輸入 passphrase」。若 ~/.ssh/ 底下有多把 key,仍建議搭配本文後面的 IdentitiesOnly=yes(單一 repo 的 core.sshCommand,或 ~/.ssh/config 的 IdentityFile),避免 SSH 亂試 key 而出現 Too many authentication failures。


單一 Repo 使用特定 SSH Key​

有時候某個 repo 需要用不同於預設的 SSH key 來連線遠端(例如這個 repo 對應的是另一個 GitLab 帳號),可以透過 core.sshCommand 只針對該 repo 設定,不影響其他專案。

設定方式​

進到專案目錄,設定 core.sshCommand(只影響這個 repo,不動全域設定):

cd /path/to/your-project
git config --local core.sshCommand "ssh -i ~/.ssh/{{YOUR_SSH_KEY}} -o IdentitiesOnly=yes"

設定完成後,.git/config 會多出這行:

[core]
sshCommand = ssh -i ~/.ssh/{{YOUR_SSH_KEY}} -o IdentitiesOnly=yes

之後這個 repo 的 git fetch / git pull / git push 都會固定用 {{YOUR_SSH_KEY}} 連線,不會混用其他 SSH key。

IdentitiesOnly=yes 是什麼?​

這是 SSH 的一個選項,加在 -o 後面使用。理解它之前,先看 SSH 預設行為:

沒有加 IdentitiesOnly=yes 時(預設行為):

SSH 連線時會自動嘗試所有可用的 key,包括:

  1. ssh-agent 裡已經載入的所有 key
  2. ~/.ssh/ 底下的預設 key(id_rsa、id_ed25519 等)
  3. 你用 -i 指定的 key

問題在於,大多數 SSH server(包括 GitLab)允許嘗試的 key 數量有上限(通常 5~6 次)。如果你的 ssh-agent 裡載了很多 key,可能在輪到正確的那把之前就被 server 踢掉,出現 Too many authentication failures。

加了 IdentitiesOnly=yes 之後:

SSH 只會使用你明確指定的 key(透過 -i 或 config 裡的 IdentityFile),不會去翻 ssh-agent 或其他預設 key。

# ❌ 沒加:SSH 可能帶了 5 把 key 去試,帶錯的先試完,正確的還沒輪到就被拒絕
ssh -i ~/.ssh/id_ed25519_hopech git@gitlab.com

# ✅ 有加:SSH 只帶這一把 key,精準命中
ssh -i ~/.ssh/id_ed25519_hopech -o IdentitiesOnly=yes git@gitlab.com
tip

只要你的 ~/.ssh/ 底下有超過一把 key,就建議加 IdentitiesOnly=yes。它確保每個連線只帶指定的 key,避免帶錯 key 被遠端拒絕。

驗證設定是否生效​

檢查 core.sshCommand 設定值​

在專案目錄下執行:

git config --local --get core.sshCommand

預期輸出:

ssh -i ~/.ssh/id_ed25519_hopech -o IdentitiesOnly=yes

測試 SSH 連線​

ssh -T git@gitlab.com -i ~/.ssh/id_ed25519_hopech -o IdentitiesOnly=yes

如果遠端已經有這把公鑰,應該會看到:

Welcome to GitLab, @YOUR_USERNAME!

驗證通過後,在這個 repo 裡直接 git fetch / git pull / git push 即可。

移除設定​

如果不再需要,可以移除這個 repo 的 SSH key 指定,回到預設行為:

git config --local --unset core.sshCommand

同一台電腦多帳號​

依目錄自動切換 SSH Key

為什麼需要這樣做?​

當你在同一台電腦上同時使用多個 GitLab(或 GitHub)帳號時,例如:

  • 帳號 A(個人)→ 專案放在 ~/personal/
  • 帳號 B(公司)→ 專案放在 ~/case/

每個帳號對應不同的 SSH key。如果每個 repo 都要手動設 core.sshCommand 太麻煩,可以用 Git 的 includeIf 依目錄自動套用,整個資料夾一次搞定。

準備工作​

為每個帳號各自產生一組 SSH key:

# 個人帳號
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_personal -C "personal@example.com"

# 公司帳號
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_company -C "company@example.com"

然後分別把對應的 .pub 公鑰,新增到各自的 GitLab / GitHub 帳號的 SSH Keys 設定頁面。

用 includeIf 依目錄自動套用​

第一步:在 ~/.gitconfig(全域設定)加入條件引入:

# 預設用個人帳號
[user]
name = personal-username
email = personal@example.com

# ~/case/ 底下的 repo 自動切換成公司帳號
[includeIf "gitdir:~/case/"]
path = ~/.gitconfig-case

第二步:新增 ~/.gitconfig-case,內容放:

[core]
sshCommand = ssh -i ~/.ssh/id_ed25519_company -o IdentitiesOnly=yes
[user]
name = company-username
email = company@example.com

效果:

  • ~/case/ 底下的 repo → 自動用 id_ed25519_company,commit 作者是公司帳號
  • 其他目錄的 repo → 用預設的個人 key 與帳號
  • 新 clone 到 ~/case/ 的 repo 也會自動套用,不需要再手動設定
tip

gitdir: 的路徑結尾要加 /,Git 才會匹配該目錄下所有子目錄的 repo。如果你的目錄不是 ~/case/,換成實際的資料夾路徑即可。

驗證多帳號設定​

# 在公司 repo 裡確認生效的帳號
cd ~/case/some-project
git config user.name # 應該顯示 company-username
git config user.email # 應該顯示 company@example.com

# 在個人 repo 裡確認不受影響
cd ~/personal/side-project
git config user.name # 應該顯示 personal-username

# 查看所有生效的 git config 及來源檔案
git config --list --show-origin

常用指令速查​

SSH Key 管理​

# 產生新的 ed25519 key
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_xxx -C "your_email@example.com"

# 查看公鑰內容(複製貼到 GitLab / GitHub)
cat ~/.ssh/id_ed25519_xxx.pub

# 列出 ~/.ssh 底下所有 key
ls -la ~/.ssh/

# 查看目前 ssh-agent 裡載入了哪些 key
ssh-add -l

# 把特定 key 加入 ssh-agent
ssh-add ~/.ssh/id_ed25519_xxx

# macOS:把 passphrase 存進 Keychain(只需一次)
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_xxx

# macOS:從 Keychain 載入已儲存的 key(可放進 ~/.zshrc)
ssh-add --apple-load-keychain -q

# 從 ssh-agent 移除所有 key
ssh-add -D

Git SSH 設定​

# 單一 repo 指定 SSH key
git config --local core.sshCommand "ssh -i ~/.ssh/id_ed25519_xxx -o IdentitiesOnly=yes"

# 查看單一 repo 的 SSH 設定
git config --local --get core.sshCommand

# 移除單一 repo 的 SSH 設定(回到預設行為)
git config --local --unset core.sshCommand

# 查看所有生效的 git config(含 includeIf 來源)
git config --list --show-origin

SSH 連線測試​

# 測試 GitLab 連線(用指定 key)
ssh -T git@gitlab.com -i ~/.ssh/id_ed25519_xxx -o IdentitiesOnly=yes

# 測試 GitHub 連線(用指定 key)
ssh -T git@github.com -i ~/.ssh/id_ed25519_xxx -o IdentitiesOnly=yes

# Debug 模式:看 SSH 實際用了哪把 key(排查問題用)
ssh -vT git@gitlab.com -i ~/.ssh/id_ed25519_xxx -o IdentitiesOnly=yes

查看 / 確認帳號設定​

# 查看目前 repo 的 remote URL(確認是 SSH 格式)
git remote -v

# 確認目前 repo 生效的 user 設定(多帳號時很重要)
git config user.name
git config user.email