前言
本專案使用 GitHub Actions 將 Hugo 編譯後的靜態網頁推送到 jess88tw/jess88tw.github.io。部署過程需要 SSH Deploy Key 來驗證推送權限。
當 Deploy Key 過期或失效時,CI/CD 會出現類似以下的錯誤訊息:
Permission denied (publickey).
Permission to jess88tw/jess88tw.github.io.git denied to deploy key
這篇文章記錄了完整的 Deploy Key 更新流程,方便日後需要時快速操作。
架構說明
本專案的 GitHub Actions workflow 使用了兩個 Secret:
| Secret 名稱 | 類型 | 用途 |
|---|---|---|
ACTIONS_DEPLOY_KEY | SSH 私鑰 | 讓 CI 有權限 push 到 jess88tw.github.io |
GIT_SUBMODULE_DEPLOY_TOKEN | GitHub PAT | 讓 CI 有權限拉取私有 submodule(目前未使用) |
私鑰像是鑰匙,公鑰像是鎖。公鑰裝在目標 repo 上,CI/CD 拿著私鑰去開門推送程式碼。
更新步驟
步驟一:產生新的 SSH 金鑰
在本機 terminal 執行(PowerShell):
ssh-keygen -t ed25519 -C "github-actions-deploy" -f gh-pages-deploy-key -N '""'
⚠️ Windows PowerShell 中
-N ""會失敗,必須用-N '""'。
執行後會在當前目錄產生兩個檔案:
| 檔案 | 內容 | 用途 |
|---|---|---|
gh-pages-deploy-key | 私鑰 🔒 | 放到 Blog repo 的 GitHub Secret |
gh-pages-deploy-key.pub | 公鑰 🔓 | 放到目標 repo 的 Deploy Keys |
步驟二:將公鑰加到目標 Repo
- 前往目標 repo 的 Deploy Keys 頁面: 👉 https://github.com/jess88tw/jess88tw.github.io/settings/keys
- 如果有舊的 deploy key,先刪除
- 點 Add deploy key
- Title:
github-actions-deploy(或任意名稱) - Key:貼上
gh-pages-deploy-key.pub的完整內容 - ✅ 一定要勾選 Allow write access(否則只有讀取權限,push 會失敗)
- 點 Add key 儲存
步驟三:將私鑰更新到 Blog Repo 的 Secret
前往 Blog repo 的 Secrets 頁面: 👉 https://github.com/你的帳號/Blog/settings/secrets/actions
找到
ACTIONS_DEPLOY_KEY,點編輯貼上
gh-pages-deploy-key的完整私鑰內容(包含 BEGIN 和 END 那行):-----BEGIN OPENSSH PRIVATE KEY----- ...(中間內容)... -----END OPENSSH PRIVATE KEY-----點 Update secret 儲存
步驟四:清理本機金鑰檔案
重要!不要把私鑰 commit 進 repo!
Remove-Item gh-pages-deploy-key, gh-pages-deploy-key.pub
步驟五:測試部署
Push 任何變更到 main branch,或到 GitHub Actions 頁面手動觸發 workflow:
👉 https://github.com/你的帳號/Blog/actions
確認部署成功 ✅
常見錯誤排查
| 錯誤訊息 | 原因 | 解法 |
|---|---|---|
Permission denied (publickey) | 金鑰過期或不存在 | 重新產生金鑰,走完步驟一到三 |
denied to deploy key | 金鑰存在但缺少寫入權限 | 確認 Deploy Key 有勾選 Allow write access |
denied to deploy key(已勾 write) | 公鑰加錯 repo | 確認公鑰是加在 jess88tw.github.io 而不是 Blog repo |
| 多把 key 衝突 | 目標 repo 有多把 deploy key | 刪掉舊的,只保留新的 |
參數速查
ssh-keygen -t ed25519 -C "github-actions-deploy" -f gh-pages-deploy-key -N '""'
│ │ │ │
│ │ │ └─ 不設密碼(CI 自動化必須)
│ │ └─ 輸出檔名
│ └─ 註解(標記用途)
└─ 加密演算法(推薦 ed25519)
總結
Deploy Key 更新的核心流程:
- 🔑 產生金鑰:使用
ssh-keygen產生一對公私鑰 - 🔓 公鑰放目標 repo:加到
jess88tw.github.io的 Deploy Keys,並勾選 Allow write access - 🔒 私鑰放來源 repo:更新 Blog repo 的
ACTIONS_DEPLOY_KEYSecret - 🧹 清理本機檔案:刪除產生的金鑰檔案,避免洩漏
- ✅ 測試部署:手動觸發 workflow 確認一切正常
最常見的坑是公鑰加錯 repo 或忘記勾選 Allow write access,更新時請特別留意。