把 Hugo 網站架設到 Codeberg 吧!
Note
這篇沒有要教怎麼安裝 Git 和 Hugo,詳細內容可以參考 JN 大大的部落格架設教學系列 和 Ivon 大大的 Hugo + GitHub + Netlify 架設教學。
如果你是要部署到 GitHub 上,請直接過去看他們的內容,不用回頭了(?);如果你是要部署到 Codeberg 上,請在設定完 Hugo(或其他網頁生成器)和 Git 後再回來繼續喔!
前言
要公開一個網站,需要一臺可以長時間開機,而且能讓別人連入的電腦。部落格也需要一個可以讓別人連入的電腦,但如果你沒有辦法這樣做,這時候就需要靠別人的電腦來幫你,你可以:
- 租一台雲端電腦,把部落格架在上面
- 用 GitHub 或其他類似平台部署部落格
但我沒有錢,所以需要把網站部署在平臺上,而我使用的平台是 Codeberg。
Codeberg 是由德國的非營利組織 Codeberg e.V 架設的開源程式碼託管平臺,詳細的歷史請在 Wikipedia 上了解,這裡就不多提了。
好了,廢話講完了,該開始講解怎麼部署部落格到 Codeberg 了。
Codeberg 網頁部署有兩種方式,一種是直接上傳網頁檔案,另外一種是上傳部落格原始碼,後續用 Forgejo Action 建置網頁。
這次教的是用原始碼部署,個人不太建議上傳 html 檔,因為後續管理可能會有點麻煩,不過還是看自己狀況決定啦 :3
正片開始
首先,當然要先到 Codeberg 註冊帳號啦!
先到 Codeberg.org 右上的 Register 註冊帳號。如果看不懂英文,網頁底下也能換語言,但翻譯好像做得不是很完全就是了。
開 repo
登入之後,按右上的加號,建立 New repository。

輸入 Repository name,其他都不用動,直接按 Create repository 就好了。
名稱隨便打就好了,只要不要跟其他 repo 名字重複就好。

然後就有新的空 repo 囉!

推上去!
在你要推的資料夾,開終端機貼上指令,啟動 git:
git init接著貼上 Codeberg 那邊 “Pushing an existing repository from the command line” 給的指令:
git remote add origin "repo 網址"
git push -u origin main然後依照指示輸入 Codeberg 的帳號和密碼(密碼不會顯示),按下 enter 後就讓它上傳啦!
上傳完就會長這樣:

回去 repo 頁面,重新整理就會看到有東西在上面了。

設定部署
欸等等,不是上傳完就結束了!Codeberg 不知道你上傳這些東西之後要幹嘛,接下來要去設定部署網頁。
Tip
這步其實可以在上傳之前完成,不過為了方便說明,就分開處理啦!
這次是要設定自動部署,接下來要設定 workflow 給 Forgejo Action。
Workflow 有點像是個給電腦看的 to-do list 或食譜,告訴他下一步應該做什麼。
所以,在部落格的根目錄執行指令:
micro .forgejo/workflows/hugo.yaml(我習慣用 micro 當純文字編輯器,你可以換成其他用起來順手的程式,像是 vim)
貼上以下內容:
name: Build and deploy
on:
push:
branches:
- main
workflow_dispatch:
concurrency:
group: ${{ forgejo.workflow }}-${{ forgejo.ref }}
cancel-in-progress: true
jobs:
build_and_deploy:
name: Build and deploy
runs-on: codeberg-small
env:
# Define tool versions
DART_SASS_VERSION: 1.101.0
GO_VERSION: 1.26.4
HUGO_VERSION: 0.164.0
NODE_VERSION: 24.18.0
# Set the build time zone
TZ: Asia/Taipei
# Set the Hugo base URL
HUGO_BASEURL: https://${{ forgejo.event.repository.owner.username }}.codeberg.page/
steps:
- name: Checkout
uses: actions/checkout@v7
with:
submodules: recursive
fetch-depth: 0
lfs: false
- name: Create a local tools directory
run: |
mkdir -p "${HOME}/.local"
- name: Install Dart Sass
run: |
echo "Installing Dart Sass ${DART_SASS_VERSION}..."
curl -sfL --output-dir "${{ runner.temp }}" -O "https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz"
tar -C "${HOME}/.local" -xf "${{ runner.temp }}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz"
echo "${HOME}/.local/dart-sass" >> "${FORGEJO_PATH}"
- name: Install Go
run: |
if [[ -f "go.mod" ]]; then
echo "Installing Go ${GO_VERSION}..."
curl -sfL --output-dir "${{ runner.temp }}" -O "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz"
tar -C "${HOME}/.local" -xf "${{ runner.temp }}/go${GO_VERSION}.linux-amd64.tar.gz"
echo "${HOME}/.local/go/bin" >> "${FORGEJO_PATH}"
fi
- name: Install Hugo
run: |
echo "Installing Hugo ${HUGO_VERSION}..."
curl -sfL --output-dir "${{ runner.temp }}" -O "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_linux-amd64.tar.gz"
mkdir "${HOME}/.local/hugo"
tar -C "${HOME}/.local/hugo" -xf "${{ runner.temp }}/hugo_${HUGO_VERSION}_linux-amd64.tar.gz"
echo "${HOME}/.local/hugo" >> "${FORGEJO_PATH}"
- name: Install Node.js
run: |
if [[ -f "package-lock.json" ]]; then
echo "Installing Node.js ${NODE_VERSION}..."
curl -sfL --output-dir "${{ runner.temp }}" -O "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz"
tar -C "${HOME}/.local" -xf "${{ runner.temp }}/node-v${NODE_VERSION}-linux-x64.tar.gz"
echo "${HOME}/.local/node-v${NODE_VERSION}-linux-x64/bin" >> "${FORGEJO_PATH}"
fi
- name: Log tool versions
run: |
echo "Logging tool versions..."
command -v sass &> /dev/null && echo "Dart Sass: $(sass --version)" || echo "Dart Sass: not installed"
command -v go &> /dev/null && echo "Go: $(go version)" || echo "Go: not installed"
command -v hugo &> /dev/null && echo "Hugo: $(hugo version)" || echo "Hugo: not installed"
command -v node &> /dev/null && echo "Node.js: $(node --version)" || echo "Node.js: not installed"
- name: Configure Git
run: |
echo "Configuring Git..."
git config --global core.quotepath false
- name: Fetch full Git history
run: |
if [[ $(git rev-parse --is-shallow-repository) == true ]]; then
echo "Fetching full Git history..."
git fetch --unshallow
fi
- name: Initialize Git submodules
run: |
if [[ -f .gitmodules ]]; then
echo "Initializing Git submodules..."
git submodule update --init --recursive
fi
- name: Install Node.js dependencies
run: |
if [[ -f package-lock.json ]]; then
echo "Installing Node.js dependencies..."
npm ci
fi
- name: Cache restore
id: cache-restore
uses: actions/cache/restore@v6
with:
path: ${{ runner.temp }}/.cache/hugo
key: hugo-${{ forgejo.run_id }}
restore-keys: hugo-
- name: Build
run: |
echo "Building the project..."
hugo build \
--gc \
--minify \
--cacheDir "${{ runner.temp }}/.cache/hugo"
- name: Cache save
uses: actions/cache/save@v6
with:
path: ${{ runner.temp }}/.cache/hugo
key: ${{ steps.cache-restore.outputs.cache-primary-key }}
- name: Deploy
uses: actions/git-pages@v2
with:
site: ${{ env.HUGO_BASEURL }}
token: ${{ forgejo.token }}
source: public/
- name: Print base URL
run: |
echo "Base URL: ${HUGO_BASEURL}"網址設定
目標網址會在 你的名稱.codeberg.page/,如果你想把這個網址留給其他網頁的話,那就在 HUGO_BASEURL 改成這樣:
HUGO_BASEURL: https://${{ forgejo.event.repository.owner.username }}.codeberg.page/${{ forgejo.event.repository.name }}/網址就會設定 你的名稱.codeberg.page/repo 名稱 了。
另外在部落格根目錄的 hugo.yaml(或 hugo.toml) 設定檔中,baseURL 也要調整成你的網址。
部署用主機
另外在 runs-on 的部署主機設定, Codeberg 有六臺部署電腦可以用(我之前看的時候是三臺),分別是 codeberg-tiny、codeberg-small、codeberg-medium,和各自再加上 -lazy。
要用 tiny, small 還是 medium,就根據你的部署工作量決定。如果你的部署工作不急,可以先讓別人跑的話,可以在後面加入 -lazy
從截圖裡面可以看到,這幾臺電腦平時都很忙,部署的時候需要排隊一下。

如果你受不了要排隊排很久的話,也可以考慮自架部署伺服器,不過這超過了我的能力範圍除非你還有其他部署工作要一起做,不然我覺得不需要另外架部署伺服器,而且有一定難度。
更新 repo
儲存完設定後要再重新上傳,在部落格根目錄開終端機:
git add -A
git commit -m "更新訊息 / 更新了什麼 / 網站更新"
git push origin另外如果 Hugo 在電腦預覽完後,會留下建置完的 /public 資料夾,但 push 的時候用不到它。資料一旦變多,整個 /public 的空間用量就會變很大,不小心 push 到 repo 的時候會很麻煩,所以我會習慣在前面的指令之前加上 rm /public -rf,像是這樣:
rm /public -rf
git add -A
git commit -m "網站更新"
git push origin接下來每次更新,都需要用 git 把檔案加入追蹤、填入新 commit 訊息,再推送更新到 Codeberg。每次都要這樣其實有點麻煩,我會把這些指令寫成一份 .sh 檔案,每次推送就直接執行檔案就好了。
啟動 Forgejo Action
更新完檔案,在 repo 的設定按 Settings → Units → Overview,勾選 “Enable integrated CI/CD pipelines with Forgejo Actions”,然後 Save Settings,把 Forgejo Actions 功能打開!

自動重新整理之後,標籤頁應該會出現 Actions,而且應該會有工作開始跑。如果沒有的話,隨便找個不會影響部落格運作的地方改一下,再重新 push,應該就會看到開始跑了。

部署成功之後,到設定好的網址看看,應該就可以看到網站上線了!

後記
對我來說,最一開始根本就不知道怎麼用,一直撞牆很久,中間也放棄了兩、三次吧,不過在寫這一篇之前,花了大概 10 分鐘測試,就把整個流程輕鬆跑完了。
讓我感到意外的是,對現在的我來說算簡單的事情,沒想到要用很長的篇幅才能寫完(是寫太多廢話吧 XD)
如果部署上有遇到其他問題,可以再來寫信問我(信箱 itsxiaobai [at] tuta.io),只要我有辦法的話啦。