前言

本專案使用 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_KEYSSH 私鑰讓 CI 有權限 pushjess88tw.github.io
GIT_SUBMODULE_DEPLOY_TOKENGitHub 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

  1. 前往目標 repo 的 Deploy Keys 頁面: 👉 https://github.com/jess88tw/jess88tw.github.io/settings/keys
  2. 如果有舊的 deploy key,先刪除
  3. Add deploy key
  4. Titlegithub-actions-deploy(或任意名稱)
  5. Key:貼上 gh-pages-deploy-key.pub 的完整內容
  6. 一定要勾選 Allow write access(否則只有讀取權限,push 會失敗)
  7. Add key 儲存

步驟三:將私鑰更新到 Blog Repo 的 Secret

  1. 前往 Blog repo 的 Secrets 頁面: 👉 https://github.com/你的帳號/Blog/settings/secrets/actions

  2. 找到 ACTIONS_DEPLOY_KEY,點編輯

  3. 貼上 gh-pages-deploy-key完整私鑰內容(包含 BEGIN 和 END 那行):

    -----BEGIN OPENSSH PRIVATE KEY-----
    ...(中間內容)...
    -----END OPENSSH PRIVATE KEY-----
    
  4. 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 更新的核心流程:

  1. 🔑 產生金鑰:使用 ssh-keygen 產生一對公私鑰
  2. 🔓 公鑰放目標 repo:加到 jess88tw.github.io 的 Deploy Keys,並勾選 Allow write access
  3. 🔒 私鑰放來源 repo:更新 Blog repo 的 ACTIONS_DEPLOY_KEY Secret
  4. 🧹 清理本機檔案:刪除產生的金鑰檔案,避免洩漏
  5. 測試部署:手動觸發 workflow 確認一切正常

最常見的坑是公鑰加錯 repo忘記勾選 Allow write access,更新時請特別留意。

參考資料