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 pullgit 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/configIdentityFile),避免 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_rsaid_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