你剛坐下,準備把程式碼推送到工作用的 筆記型電腦上管理不同的 Git 帳號時,這種挫折感非常常見。

你或許會手動切換金鑰,或者乾脆使用不同的機器。這些權宜之計既浪費時間,也容易出錯。其實有更好的方案:你可以把多個 SSH 金鑰設定為協同運作。為每個服務產生一把獨立的新 SSH 金鑰;然後建立一個統一的設定檔。這個檔案會告訴系統,針對不同主機應該使用哪一把金鑰。如此設定之後,就無需再手動切換。你的所有遠端連線都將擁有一套長期穩定、更加順暢的工作流程。

如何在你的系統上設定多個 SSH 金鑰

所有驗證檔案都應存放在你本機的 ~/.ssh 目錄中。這個目錄用來儲存私鑰與公鑰檔案配對。將所有內容集中管理,不僅更方便,也能確保 SSH 用戶端自動找到正確的憑證。

為每個服務產生獨立金鑰

首先,為你使用的每個遠端服務建立一組獨立的金鑰對。下面這條指令會產生一個帶有自訂檔名的新 SSH 金鑰:

ssh-keygen -t ed25519 -C "work@email.com" -f ~/.ssh/gitlab_work

-f 參數用於指定輸出檔名。如果不使用它,系統會預設產生到 id_ed25519,這可能會覆蓋你既有的金鑰。建議使用像 github_personalgitlab_work 這樣具有描述性的名稱,方便一眼辨識每把金鑰的用途。

對於新金鑰而言,Ed25519 是建議使用的演算法。與 RSA 相比,它通常具備更好的安全性、更快的效能以及更小的金鑰體積。大多數現代 Linux 發行版與 OpenSSH 6.5 及以上版本都已完整支援它。不過,某些較舊的系統或特定雲端服務供應商可能仍要求使用 RSA。如果你出於相容性需求而選擇 RSA,請至少使用 3072 位元,最好是 4096 位元。

當指令提示你輸入 passphrase 時,請務必設定一個。這層額外保護可在他人取得你機器存取權限時,進一步保護你的私鑰。除非你稍後設定了 agent,否則每次連線時都需要輸入這個 passphrase。

將公鑰加入遠端主機

在產生每組金鑰後,你還必須把對應的公鑰註冊到相關服務中。對於你的工作 GitHub 帳號,可以進入 Settings → SSH keys,然後貼上對應 .pub 檔案中的內容。對於託管在公司伺服器上的工作專案儲存庫,你可能需要將該公鑰附加到目標機器的 ~/.ssh/authorized_keys 檔案中。

ssh-copy-id 工具可以大幅簡化這個流程。執行 ssh-copy-id -i ~/.ssh/gitlab_work.pub user@server.com,即可在不覆蓋現有項目的前提下,把公鑰附加到遠端主機中。當你需要在多台機器之間管理多把金鑰時,這個指令會非常高效。

在開始設定統一的 config 檔案之前,建議先使用 -i 選項分別測試每一把金鑰。只要看到成功提示,就表示該金鑰本身可正常使用。這一步能在你建立完整設定前,提前找出問題。

使用 Config 檔案管理多個 SSH 金鑰

~/.ssh/config 檔案就是整套設定的指揮中心。這個純文字檔會明確告訴系統:連線不同遠端主機時,應該出示哪一把金鑰。你可以建立與主機名稱匹配的規則,並為這些規則指定對應的身份檔案。如此一來,就不再需要猜測或手動選鑰匙。

設定主機別名與 IdentityFile

使用任意文字編輯器開啟 config 檔案。你需要建立若干設定區塊來定義連線參數。每個設定區塊都以一行 Host 開頭,用來建立你連線時輸入的別名。HostName 指定實際網域名稱。User 指定登入使用者名稱。IdentityFile 則指定要使用的私鑰路徑。

假設你同時管理工作 GitHub 帳號與個人 GitHub 帳號,你的 config 檔案可以寫成這樣:

# --- 用於工作 GitHub ---
Host github.com-work
HostName github.com
User git
IdentityFile ~/.ssh/github_work
IdentitiesOnly yes

# --- 用於個人 GitHub ---
Host github.com-personal
HostName github.com
User git
IdentityFile ~/.ssh/github_personal
IdentitiesOnly yes

IdentitiesOnly yes 這個指令非常關鍵。當你的 agent 中載入了多把 SSH 金鑰時,建立連線時系統可能會依序嘗試多把金鑰,直到找到正確的一把。伺服器會拒絕錯誤的金鑰,而多次失敗甚至可能觸發安全限制。這個指令會確保系統只提供目前設定區塊中指定的那一把金鑰,從而避免誤送金鑰與驗證失敗。

你也可以在同一個主機設定中寫多個 IdentityFile。SSH 會依序嘗試這些金鑰,直到伺服器接受其中某一把。這種做法在你輪替金鑰或透過多種憑證保留存取能力時非常有幫助。

還有一點需要注意:避免在設定檔後面又重新覆蓋前面已經修改過的主機規則。例如你先建立了一個 Host github.com-work 別名並修改了 hostname,後面又新增了一個針對 Host github.com 的設定並指定了不同的金鑰,agent 可能會覆蓋你前面的規則。建議讓別名組織清楚、規則足夠具體。

使用萬用字元設定預設組態

當你需要管理很多伺服器時,萬用字元可以大幅簡化 SSH 設定。星號(*)可匹配零個或多個字元,問號(?)則匹配剛好一個字元。藉助這些模式,你可以為整組主機套用統一設定,而不必為每台機器都另外撰寫一個設定區塊。

模式語法:一個模式由零個或多個非空白字元、*(匹配零個或多個字元的萬用字元)或 ?(匹配剛好一個字元的萬用字元)組成。

例如,你可以為某個網域下的所有主機設定統一參數:

Host *.company.com
User deploy
IdentityFile ~/.ssh/company_deploy
IdentitiesOnly yes

這條規則會套用到 staging.company.com、production.company.com 以及其他任何子網域。你也可以匹配 IP 範圍。例如,Host 192.168.0.? 這個模式會匹配 192.168.0.0 到 192.168.0.9 範圍內的任意主機。

萬用字元也支援繼承式匹配。比如主機名稱 acmereplica 可能會先匹配一個通用的 Host acme* 設定區塊以取得使用者設定,再匹配更具體的 Host acmereplica* 設定區塊以取得其 hostname。SSH 會按照由上而下的順序讀取設定,並對每個參數採用第一個匹配到的值。

這種方式的擴充性非常好。新增一台伺服器時,藉助萬用字元往往只需要補上兩行設定即可。你無須重複撰寫大量共用參數,萬用模式會替你處理其餘工作。

Host * 設定區塊可以作為你的預設組態。請將它放在檔案底部。所有沒有匹配到更具體規則的主機,都會繼承這裡的設定。例如你可以在這裡統一設定 AddKeysToAgent yes,以自動載入金鑰。

你的 SSH config 檔案會徹底改變你管理遠端連線的方式。你只需要把多個 SSH 金鑰設定一次,之後就可以不再操心手動選鑰匙的問題。系統會自動把每次連線路由到正確的設定。建立好檔案後,請記得測試,確認每個主機都使用了預期的金鑰。

將多組 SSH 金鑰加入 Agent

SSH agent 是一個背景程式,用來在記憶體中保存已解密的私鑰。它可以讓你不必在每次連線遠端主機時都重複輸入 passphrase。當你同時使用多組 SSH 金鑰時,agent 幾乎是不可或缺的。它可以統一管理所有金鑰,並在驗證時自動提供正確的那一把。

使用 ssh-add 實現自動驗證

首先,在終端機工作階段中執行 eval "$(ssh-agent -s)" 來啟動 agent。這個指令會啟動 agent,並設定它所需的環境變數。接著,使用 ssh-add 指令把你的私鑰加入其中。

agent 會為每把金鑰提示你輸入一次 passphrase。之後,它就會把解密後的私鑰保存在記憶體中。你可以執行 ssh-add -l 來確認目前已載入哪些金鑰。這個指令會列出 agent 目前持有的所有指紋。

關於 SSH agent forwarding 的安全建議:Agent forwarding 可以讓你透過堡壘機使用本機金鑰。但是,如果轉發目標主機被攻破,攻擊者就可能劫持你的金鑰。你管理的金鑰越多,風險也越大,因為被攻破的目標可能暴露你所有被轉發的金鑰。因此,只有在完全信任目標伺服器時才應啟用 agent forwarding。更安全的替代方案是使用 ProxyJump-J),因為它不需要轉發金鑰本身:ssh -J bastion.example.com user_x@internal.example.com

讓金鑰在重新開機後持續可用

agent 只會把金鑰保存在記憶體中。當你重新啟動機器後,agent 中已載入的金鑰會被清空。除非你額外設定持久化機制,否則每次開機後都需要手動重新加入。

在 macOS 上,你可以將 passphrase 儲存在 Keychain 中。執行 ssh-add --apple-use-keychain ~/.ssh/github_personal,即可在加入金鑰的同時安全儲存其 passphrase。然後,在你的 ~/.ssh/config 檔案中 Host * 這類通用設定區塊下加入以下內容:

UseKeychain yes
AddKeysToAgent yes

UseKeychain yes 指令會告訴 SSH 自動從 Keychain 中讀取 passphrase。這樣在機器重新啟動後,agent 也能自動載入你的金鑰,而無需再次手動輸入。

在 Linux 上,做法會略有不同。有些發行版支援 ssh-add -K,但這個參數並不通用。更可靠的方式是使用像 gnome-keyringKWallet 這樣的金鑰圈管理工具。它們可以與你的桌面環境整合,並在你登入時自動解鎖金鑰。或者,你也可以建立一個開機啟動腳本,在每次系統啟動後自動載入所需金鑰。

ssh-agent 能顯著改善你的工作流程。你只需把金鑰設定一次,後續驗證過程就會在背景悄然完成。如此一來,在多個 Git 服務之間來回切換時,你會節省大量時間,也能減少不必要的挫折感。

測試你的多 SSH 金鑰設定

你已經產生了獨立金鑰、撰寫了 config 檔案,也把所有內容載入了 agent。現在就到了驗證設定是否真正生效的時候。逐一測試每一條連線,可以確保設定完全符合預期。這一步能在問題打斷你的工作流程之前,先把它們找出來。

使用 -T 參數驗證連線

-T 參數會告訴 SSH 停用虛擬終端機分配。對於 Git 託管平台而言,這非常合適,因為你只需要驗證身分是否成功,而不需要真正開啟一個互動式 shell。請針對每個已設定的主機分別執行測試指令。

例如,針對你的個人 GitHub 帳號,執行:

ssh -T git@github.com-personal

注意,這裡的主機名稱使用的是你在 config 檔案中定義的別名。SSH 會讀取這個別名,找到對應的設定區塊,並使用正確的身份檔案。成功時,回傳訊息通常類似於:「Hi username! You’ve successfully authenticated, but GitHub does not provide shell access.」這表示 GitHub 已辨識你的金鑰,並將其關聯到正確的帳號。

對於你的工作 GitLab 執行個體,可以執行:

ssh -T git@gitlab.com-work

GitLab 會回傳一則包含你使用者名稱的歡迎訊息。每一次成功提示,都代表你的 config 檔案已經正確地將連線路由到目標設定。系統無需任何手動介入,就自動選擇了合適的金鑰。

請把你定義過的每個主機都測試一次。你可以根據 config 檔案中的別名列出一份清單,再逐項驗證。這樣可以第一時間發現拼字錯誤、路徑不正確或設定不匹配等問題。

如果測試失敗,請仔細查看錯誤訊息。出現「Permission denied (publickey)」通常表示 SSH 未能完成驗證。這時請檢查 IdentityFile 路徑是否正確;確認公鑰是否已加入遠端主機;並核對你輸入的別名是否與 config 中完全一致。

透過複製儲存庫確認設定生效

-T 測試可以證明驗證鏈路沒有問題。但在真實情境中,你最終還是要複製儲存庫。因此,做一次實際複製測試,才能證明整套設定在正常使用中也能穩定運作。

先切換到本機上的一個暫存目錄,然後複製你個人 GitHub 帳號下的私有儲存庫:

git clone git@github.com-personal:username/private-repo.git

Git 會使用這個主機別名來查找對應設定,並自動選擇你的個人金鑰。儲存庫應能順利下載,無需額外提示你輸入 passphrase 或手動選擇金鑰。這表示你的個人設定已經運作正常。

接著,測試工作環境。切換到另一個目錄,並從公司 GitLab 伺服器複製工作專案儲存庫:

git clone git@gitlab.com-work:company/work-project.git

同樣地,別名會把 SSH 引導到正確的身份檔案。工作專案儲存庫也應該能夠毫無衝突地順利複製下來。至此,你就驗證了兩套金鑰路徑可以同時正常運作。系統已經能夠區分不同主機,並在每次連線時自動套用正確的憑證。

如果你還設定了其他服務,也請重複這個流程。為每個主機都複製一個測試儲存庫。如此全面的驗證方式,能確保每個別名都真正可用,從而避免在日常工作中遭遇意外。

成功完成複製,就表示你已經做到:只需設定一次多個 SSH 金鑰,之後即可長期穩定使用。整個驗證過程會在背景靜默完成。你可以在個人專案與工作專案之間自由切換,無需手動切換金鑰,也不會再被權限錯誤打斷,更不會浪費多餘時間。

現在,你的多 SSH 金鑰已經能夠無縫協同運作。config 檔案會精準地將連線路由到正確目標,agent 則會在背景自動提供憑證。你的工作流程將因此變得順暢而高效。

排查多個 SSH 金鑰之間的衝突

即使設定過程已經足夠謹慎,問題仍然可能出現。最常見的通常有兩類:權限錯誤,以及系統使用了錯誤的金鑰。只要理解問題根源,這兩類故障一般都很容易修復。

修復「Permission Denied (publickey)」錯誤

OpenSSH 會在本機上嚴格檢查權限。如果你的私鑰檔案權限過於寬鬆,SSH 會直接拒絕使用它。你可能會看到像是「UNPROTECTED PRIVATE KEY」或「Permissions are too open.」之類的提示。這些錯誤其實是在保護你,避免使用不安全的設定。

在 macOS 或 Linux 上,執行 chmod 600 ~/.ssh/your-key-file 即可修復私鑰權限。Windows 使用者則需要透過內容視窗的 Security 索引標籤進行調整。以滑鼠右鍵點擊金鑰檔案,選擇 Properties,然後進入 Security,再點選 Advanced。關閉繼承,並移除除你自己之外其他使用者的權限。

解決系統使用了錯誤金鑰的問題

有時 SSH 會把錯誤的金鑰送給遠端主機。在沒有其他明確指示的情況下,系統會預設嘗試 ~/.ssh/id_rsaid_ed25519。你的 config 檔案本應覆蓋這種預設行為,但實際設定時難免會有疏漏。

此時可以用詳細模式進行診斷。執行 ssh -v -T git@github.com-personal,查看系統到底出示了哪一把金鑰。輸出資訊會依序顯示每一次驗證嘗試,你可以很快找出其中的錯配問題。

你也可以核對指紋。例如,GitHub 會公開發布其 RSA 主機金鑰指紋。你可以把連線時顯示的指紋與官方公布值進行比對。若兩者一致,就表示你連線到的是正確的伺服器。

最後,再確認一次:對應的公鑰是否確實已加入遠端服務中。進入你的 Git 託管平台 SSH 設定頁面,檢查正確的公鑰是否存在。請記住,私鑰永遠不應離開你的本機。ssh-agent 只會在本機持有私鑰,並僅在驗證時出示它。絕對不要與任何伺服器分享或複製你的私鑰。

至此,你已完成整個流程。每個服務都有獨立金鑰;結構清楚的 ~/.ssh/config 檔案負責為每次連線精準路由;所有測試也都表明你的設定運作正常。這整個流程,就是如何將多個 SSH 金鑰設定為可同時使用的完整方法。

從現在開始,你不必再手動切換金鑰。正確的金鑰會始終對應正確的主機。ssh-agent 會在背景靜默管理所有憑證。這種設定方式不僅適用於 Git 服務,也同樣適用於任何遠端伺服器。

請務必妥善保管私鑰。每一把金鑰都應設定 passphrase。保持目錄整潔,刪除不再使用的項目,並在需求變化時及時更新 config 檔案。這些習慣將幫助你長期高效地維護整套工作流程,也會讓你每天都節省更多時間。

常見問題

我可以為多個服務共用一把 SSH 金鑰嗎?

從技術上來說可以,但並不建議。為不同服務使用獨立金鑰,可以在某一把金鑰外洩時將影響範圍降到最低,也更便於後續進行控管與撤銷。

如果之後我要新增一把 SSH 金鑰,會發生什麼事?

只需用一個清楚易懂的檔名產生新金鑰;將公鑰加入對應遠端主機;在 config 檔案中新增一個設定區塊;然後執行 ssh-add 把它載入 agent 即可。

為什麼 SSH 總是一再要求我輸入 passphrase?

因為系統重新開機後,agent 中已載入的金鑰會被清空。你可以在 config 檔案中加入 AddKeysToAgent yes。如果你使用 macOS,請搭配 ssh-add --apple-use-keychain;如果你使用 Linux,則可以設定相應的 keychain 管理工具。

這套方案能在 Windows 上使用嗎?

可以。Windows 版 OpenSSH 支援相同的 config 檔案結構。你的目錄路徑應使用 %USERPROFILE%\.ssh\。這些指令在 PowerShell 中也可以直接使用,無需修改。