用 GitHub Actions + Self-hosted Runner 建立自動部署流程

|4 min read|Updated: |
CI/CDGitHub ActionsDevOpsSelf-hostedWorkflow

最近每次更新部落格,流程是這樣:寫完文章 → push 到 GitHub → SSH 進舊電腦 → 手動執行 deploy.sh

明明 code 已經上去了,還要再多一步手動部署,總覺得很多餘。直到設定了 GitHub Actions Self-hosted Runner,現在的流程變成:寫完文章 → push → 等待 → 部署完成。


架構說明

我的部落格是部署在家裡的舊電腦(當 NAS 用),透過 Cloudflare Tunnel 對外服務,不需要有固定 IP 或開放 port。

git push
  │
  ▼
GitHub 偵測到 push 事件
  │
  ▼
觸發 GitHub Actions Workflow
  │
  ▼
NAS 上的 Self-hosted Runner 收到任務
  │
  ▼
Runner 在本機執行 deploy.sh
(git pull → npm ci → npm run build → pm2 restart)
  │
  ▼
部署完成

為什麼不用 GitHub-hosted Runner?

GitHub 提供的 runner 跑在它們的雲端伺服器,要部署到你自己的機器,就需要 SSH 進去或呼叫 webhook。

Self-hosted Runner 的思路反過來:由你的機器主動去 GitHub 輪詢有沒有新任務,不需要外部能連進你家的網路,因此防火牆完全不用動,Cloudflare Tunnel 也不受影響。


設定步驟

1. 在 GitHub 建立 Runner

前往 repo → Settings → Actions → Runners → New self-hosted runner

按照我舊電腦的系統,我選 Linux / x64,選完後 GitHub 會給你一段安裝指令。

Figure 1: New self-hosted runner 頁面,GitHub 會自動產生含一次性 token 的安裝指令。

2. 在 NAS 安裝 Runner

使用 GitHub 頁面上給你完整的指令,下載、解壓、以及帶有一次性 token 的 config.sh,照著貼上執行即可。 執行過程會問幾個問題(runner 名稱、labels、工作目錄等),全部按 Enter 使用預設值就好。

不需要用 ./run.sh,那是前景執行,關掉 terminal 就停了。

3. 安裝為 systemd Service

接著可以執行

sudo ./svc.sh install
sudo ./svc.sh start

svc.sh install 會把 runner 註冊成系統服務,重開機後也會自動啟動。

確認狀態:

sudo systemctl status actions.runner.*

看到 Active: active (running) 就完成了。

Figure 2: systemctl status 輸出,Active: active (running) 代表 runner 已成功註冊為系統服務,重開機也會自動啟動。

4. 建立 Workflow 檔案

在 repo 裡建立 .github/workflows/deploy.yml

name: Deploy to NAS

on:
  push:
    branches:
      - main

jobs:
  deploy:
    name: Build & Deploy
    runs-on: self-hosted

    steps:
      - name: Run deploy script
        working-directory: /你的專案絕對路徑
        run: bash scripts/deploy.sh

runs-on: self-hosted 是告訴 GitHub 這個 job 要交給自己的 runner 執行,而不是 GitHub 的雲端機器。

驗證流程

全部設定完後,回到 GitHub repo → Settings → Actions → Runners,確認 runner 狀態是綠色 Idle

然後 push 任何 commit,前往 Actions 頁面,就能看到 workflow 即時執行的 log

成功或失敗都有紀錄,失敗時 GitHub 還會寄通知信,比手動執行更容易發現問題。

Figure 3: GitHub Actions 頁面的即時執行 log,每個步驟的輸出一目瞭然,部署失敗時也會自動寄送通知信。


小結

整個設定花了不到半小時,但用完之後我覺得方便很多:

  • git push = 部署完成,不需要手動 SSH
  • 每次部署都有 log,失敗時有通知
  • Runner 在本機輪詢,不需要開任何 port 或修改防火牆

對於把服務部署在自家機器的人來說,Self-hosted Runner 是比 webhook 更簡單、更安全的選擇。