自架服務 Docker Forgejo Git CI/CD GitHub Actions

GitHub 太方便但程式碼放在別人手上:Forgejo 讓你在 VPS 上自架 Git 加 CI/CD

Forgejo 是 Gitea 的社群分支,單一 binary 就能跑起完整的 Git 平台,內建與 GitHub Actions 相容的 CI/CD 系統。本文涵蓋 Docker Compose 部署、Forgejo Actions runner 設定、workflow 撰寫,以及什麼情境該自架、什麼情境別碰。

GitHub 免費、好用、生態系完整,但它本質上是一個中心化的 SaaS——程式碼存在微軟的伺服器上,CI/CD 的 runner 跑在微軟的機器上,Actions 的免費額度用完就得付錢或等月初重置。對個人 side project 來說這不是問題;但當程式碼涉及客戶資料、商業邏輯,或是團隊的部署流程全部綁在 GitHub Actions 上時,把所有雞蛋放在同一個籃子裡就值得重新考慮。

Forgejo 是目前自架 Git 平台最值得關注的選項。它從 Gitea 分支出來,由非營利社群治理,用 Go 寫成單一 binary,512MB RAM 就能跑起來。關鍵賣點是 Forgejo Actions——一套與 GitHub Actions 語法高度相容的 CI/CD 系統,既有的 workflow YAML 幾乎不用改就能搬過來。2026 年 4 月釋出的 v15.0 LTS 進一步補上了 ephemeral runner、OIDC 認證、repository-scoped token 等生產環境需要的功能。

Gitea 還在,為什麼要選 Forgejo

Gitea 跟 Forgejo 長得幾乎一樣,功能也高度重疊,但治理模式完全不同。

Gitea 在 2022 年成立了商業公司 Gitea Ltd.,核心開發資源開始向付費的 Gitea Cloud 傾斜。社群貢獻者發現 PR review 變慢、討論透明度下降,於是一群人在同年分支出 Forgejo,交給 Codeberg e.V.(德國非營利組織)管理。Forgejo 承諾所有程式碼永遠是自由軟體,不走開放核心(open core)的商業路線。

實務上的差異:Forgejo 的安全修補通常比 Gitea 快,每月固定出 patch release。v15.0 拿到 LTS 標記,官方支援到 2027 年 7 月。授權方面,Forgejo 採 GPL,Gitea 是 MIT——前者確保任何衍生版本都必須開源,後者允許被包進專有產品。長期維運來看,Forgejo 是比較穩的選擇。

Docker Compose 部署

一台跑 Ubuntu 24.04 的 VPS,2 核 CPU、2GB RAM 就夠。先確認 Docker Engine 24 以上和 Docker Compose plugin 已經裝好。

建立工作目錄:

1
mkdir -p /opt/forgejo && cd /opt/forgejo

建立 docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
networks:
forgejo:
external: false

services:
server:
image: codeberg.org/forgejo/forgejo:15
container_name: forgejo
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__database__DB_TYPE=postgres
- FORGEJO__database__HOST=db:5432
- FORGEJO__database__NAME=forgejo
- FORGEJO__database__USER=forgejo
- FORGEJO__database__PASSWD=changeme
- FORGEJO__actions__ENABLED=true
restart: always
networks:
- forgejo
volumes:
- ./forgejo-data:/data
- /etc/localtime:/etc/localtime:ro
ports:
- '3000:3000'
- '222:22'
depends_on:
db:
condition: service_healthy

db:
image: postgres:16-alpine
container_name: forgejo-db
environment:
- POSTGRES_USER=forgejo
- POSTGRES_PASSWORD=changeme
- POSTGRES_DB=forgejo
restart: always
networks:
- forgejo
volumes:
- ./postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "forgejo"]
interval: 10s
timeout: 5s
retries: 5

啟動服務:

1
docker compose up -d

打開 http://你的IP:3000,第一次進入會看到安裝精靈。資料庫欄位已被環境變數填好,確認網站 URL 和管理員帳號後按下安裝就完成了。整個過程不到五分鐘。

裝完後立刻建立管理員帳號——Forgejo 預設讓第一位註冊者成為管理員,拖著不設定等於把管理權限暴露在公網上。

正式環境加上反向代理

3000 port 直連只適合測試。正式環境該在前面架 Caddy 或 Nginx 處理 HTTPS。以 Caddy 為例,Caddyfile 三行搞定:

1
2
3
git.yourdomain.com {
reverse_proxy localhost:3000
}

同時把 docker-compose.yml 裡的 ports 從 '3000:3000' 改成 '127.0.0.1:3000:3000',讓 Forgejo 只接受本機連線。SSH 的 222 port 維持對外,方便 git clone 走 SSH 協定。

Forgejo Actions:自己的伺服器跑自己的 CI/CD

Forgejo Actions 直接相容 GitHub Actions 的 workflow 語法。.forgejo/workflows/ 目錄放 YAML 檔,on: [push]jobsstepsuses 這些關鍵字和 GitHub 一模一樣。GitHub Marketplace 上多數主流 action(像 actions/checkout@v4actions/setup-node@v4)直接搬過來就能用,不需要改寫。

上面的 docker-compose.yml 已經透過 FORGEJO__actions__ENABLED=true 啟用了 Actions。接下來要起一個 runner 來實際執行 CI job。

到 Forgejo 管理介面的 Site Administration → Runners,點選 Create Runner 取得 registration token。然後回到 /opt/forgejo,在 docker-compose.yml 裡加入 runner 服務:

1
2
3
4
5
6
7
8
9
10
11
12
13
runner:
image: data.forgejo.org/forgejo/runner:6
container_name: forgejo-runner
depends_on:
- server
environment:
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- ./runner-data:/data
- /var/run/docker.sock:/var/run/docker.sock
restart: always
networks:
- forgejo

注意:runner 掛載 /var/run/docker.sock 代表它擁有主機 Docker 的完整控制權(等同 root 權限)。正式環境建議把 runner 放在獨立 VM/主機或採用更強隔離的執行方式,避免 CI 工作負載影響到整台伺服器。

啟動 runner 容器後,執行註冊指令:

1
2
3
4
5
docker compose exec runner forgejo-runner register \
--instance http://server:3000 \
--token <你的-registration-token> \
--name vps-runner \
--no-interactive

註冊成功後重啟 runner 讓設定生效:

1
docker compose restart runner

到任一 repository 的 Settings → Units 確認 Actions 已勾選,然後在專案根目錄建 .forgejo/workflows/ci.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
on:
push:
branches: [main]

jobs:
build:
runs-on: docker
steps:
- uses: actions/checkout@v4
- name: Run tests
run: |
echo "Running tests..."
npm ci && npm test

Push 到 main,Actions 頁籤就會出現執行記錄。從原始碼到 build artifact 到 runner 的運算時間,全部在自己的 VPS 上完成,沒有免費額度的問題,也不會因為 GitHub 的 runner queue 排隊等半天。

v15.0 值得注意的三件事

Ephemeral runner 讓 runner 執行完一個 job 後自動銷毀 credential 並退出。搭配 Docker 或 systemd 的自動重啟機制,就能做到「用完即丟」的 runner 池——每個 CI job 拿到的都是一次性 token,沒有長期憑證留在機器上被利用。

Repository-scoped access token 把 API token 的權限收窄到特定 repository。以前只能建 user-level token,權限過大;現在可以為每個自動化流程只開放它需要存取的 repo,符合最小權限原則。

Workflow OIDC 認證 讓 CI job 用 Forgejo 簽發的 JWT 存取第三方服務,不需要把 static token 塞進 CI secret。這個功能等同 GitHub 的 OIDC identity provider,想串接雲端部署或 container registry 時能避免靜態金鑰外洩的風險。

什麼情境不適合自架

自架 Git 平台不是零成本。Forgejo 本身很輕,但維護負擔在其他地方。

備份是最容易被忽略的環節。Git repository 資料、PostgreSQL metadata、Actions artifact——三個地方都要定時備份到異地儲存。Forgejo 內建 forgejo dump 指令能打包整份資料,但排程和遠端同步得自己用 cron 加 rclone 或類似工具串起來,沒人盯就等於沒備份。

升級也需要持續關注。Forgejo 每月出 patch,LTS 每季一次,偶爾會有 breaking change——v15.0 就改了預設 cookie 名稱和 rootless 部署的設定路徑。小團隊如果沒有人願意定期讀 release notes,GitHub 或 GitLab SaaS 反而更省心。

Action 的生態系也比不上 GitHub Marketplace。多數主流 action 能用,但遇到深度依賴 GitHub API 的 action(例如直接呼叫 GitHub REST API 取 PR 資訊的套件)就需要改寫。如果團隊的 workflow 大量仰賴 GitHub-specific 的整合,搬遷成本可能高於預期。

適合的場景很明確:三到五人的開發團隊、希望程式碼和 CI/CD 留在自己的基礎設施上、有人願意每月花一小時處理更新與備份。符合這些條件,Forgejo 的投資報酬率很高。

把開發基礎設施留在自己手上

Forgejo 把 Git hosting、code review、issue tracking、container registry 和 CI/CD 收進同一套平台,跑在一台 VPS 上只佔 512MB RAM。對重視資料主權和部署自主性的團隊來說,這是門檻最低的完整方案。需要一台穩定的 VPS 來跑 Forgejo,NCSE Network 提供臺灣是方電訊機房的雲端主機,搭載 Intel Gold CPU 與 NVMe SSD,延遲低、效能穩定,支援 7 天免費試用,直接開機測試整套部署流程。

需要穩定的雲端主機?

NCSE Network 提供企業級 VPS,7 天免費試用,臺灣是方電訊機房,99% SLA 保證。

查看 VPS 方案 →