0%

基于 kekxv/gitea-pages 与 Gitea Actions 构建静态站点托管服务

基于 kekxv/gitea-pages 与 Gitea Actions 构建静态站点托管服务

Gitea 本身是一个轻量级的 Git 服务,但官方暂未提供类似 GitHub Pages 的原生静态站点托管功能。如果你需要在 Gitea 环境中实现自动化部署并托管静态文档或前端构建产物,可以引入开源项目kekxv/gitea-pages 作为解决方案。

本文将介绍该项目的工作机制,并重点解析服务端的 Docker 部署方式,以及如何通过 Gitea Actions 编写 CI/CD 工作流,实现代码提交后的全自动构建与部署。

1. 架构简述:kekxv/gitea-pages 如何工作?

kekxv/gitea-pages 的定位是一个适配 Gitea 的无状态(Actionless)静态站点托管服务。其底层运行逻辑如下:

  1. Webhook 驱动:通过在 Gitea 中配置全局或仓库级的 Webhook,监听 push 事件。
  2. 分支同步:当检测到代码被推送到约定的分支(如 gh-pages)时,服务会通过浅克隆(Shallow Clone)将该分支的内容拉取到服务器本地。
  3. Nginx 路由分发:结合泛域名解析(如 *.pages.example.com),内置的 Nginx 容器会将请求路由到对应仓库的克隆目录中,实现类似 username.pages.example.com/repo 的访问效果。
  4. 权限校验:针对私有仓库,它支持通过 Gitea 的 OAuth2 机制或 Access Token 进行访问鉴权。

2. 服务端部署:Docker Compose 配置

kekxv/gitea-pages 的服务端架构解耦为两个核心容器:负责处理 Webhook 和拉取代码的 deployer,以及负责解析泛域名和托管静态文件的 pages-nginx

你可以通过以下 docker-compose.yaml 文件快速拉起服务:

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
services:
deployer:
image: ghcr.io/kekxv/gitea-pages/deployer:latest
restart: unless-stopped
environment:
# 必填项:你的 Pages 泛域名基础域名 (如 example.com)
- DOMAIN=${DOMAIN:-}
# 必填项:Webhook 密钥 (需与 Gitea 后台配置的 Webhook 密钥保持一致)
- WEBHOOK_SECRET=${WEBHOOK_SECRET:-}

# Gitea API 地址 (用于 OAuth 和 API 调用)
- GITEA_API_URL=${GITEA_API_URL:-}

# OAuth2 配置 (用于私有仓库的访问授权)
# 需在 Gitea 中创建: 设置 -> 应用 -> OAuth2 应用
- OAUTH_CLIENT_ID=${OAUTH_CLIENT_ID:-}
- OAUTH_CLIENT_SECRET=${OAUTH_CLIENT_SECRET:-}
- OAUTH_REDIRECT_URL=${OAUTH_REDIRECT_URL:-}

# 可选项:用于私有仓库的备用方案 (如果不使用 OAuth)
# - GITEA_ACCESS_TOKEN=${GITEA_ACCESS_TOKEN:-}
volumes:
# 共享数据卷:用于存储拉取的静态文件
- ./pages/webroot:/var/www/pages
# 部署器数据卷:持久化存储 deployer 的运行状态
- ./pages/deployer:/var/lib/deployer:rw
ports:
- "8080:8080" # Webhook 接收端口

pages-nginx:
image: ghcr.io/kekxv/gitea-pages/nginx:latest
restart: unless-stopped
volumes:
# 挂载共享数据卷 (配置为只读权限 ro,保障文件安全)
- ./pages/webroot:/var/www/pages:ro
ports:
- "8888:80" # Nginx 静态文件 Web 访问端口

核心配置解析:

  • **数据卷共享 (Volumes)**:deployer 将拉取的静态文件写入 ./pages/webroot,而 pages-nginx 以只读 (ro) 模式挂载该目录,实现了构建产物写入与对外发布的安全隔离。
  • **端口映射 (Ports)**:
    • 8080 端口用于接收 Gitea 侧发出的 Webhook 请求,需确保 Gitea 实例能够访问该端口。
    • 8888 端口为 Nginx 服务的暴露端口,生产环境中通常需要在外层再配置一层反向代理(如 Nginx 或 Traefik),将泛域名 *.pages.example.com 指向此端口。
  • 私有仓库鉴权:环境变量中提供了 OAuth2 和 GITEA_ACCESS_TOKEN 两种方式,供拉取私有仓库内容时进行身份认证。

3. CI/CD 配置:使用 Gitea Actions 自动部署

在服务端配置完成并成功运行后,开发者端的任务是将构建产物自动化地推送到 gh-pages 分支。由于 Gitea Actions 兼容 GitHub Actions 的语法和生态,我们可以直接利用现有的 Actions 插件。

以下是在 Gitea 仓库中实现自动打包并推送到 gh-pages 分支的标准 workflow 配置文件(保存路径:.gitea/workflows/deploy.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
name: Deploy to gh-pages

on:
push:
branches:
- main # 监听 main 分支的代码推送
workflow_dispatch: # 支持手动触发流水线

jobs:
build:
runs-on: ubuntu-latest

# 关键配置:显式授予 GITHUB_TOKEN 对 contents 的写入权限
permissions:
contents: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
# 直接调用 Gitea 注入的环境变量进行鉴权
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist # 指定需要发布的构建产物目录
publish_branch: gh-pages # 目标分支
force_orphan: true # 使用孤儿分支模式

# Git 提交的作者信息配置
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'

4. Workflow 核心配置解析

上述 YAML 文件中有几个针对 Gitea Actions 环境的必要配置,需要特别注意:

  • permissions: contents: write (写入权限声明)
    在默认的安全策略下,Runner 分配的 GITHUB_TOKEN 可能是只读权限。部署步骤需要向仓库的 gh-pages 分支执行 git push 操作,因此必须显式声明 contents: write 提升 Token 权限,否则会在部署阶段触发 HTTP 403 权限拒绝异常。
  • github_token: ${{ secrets.GITHUB_TOKEN }} (免密认证)
    Gitea 在执行 Action 时,会在当前上下文中自动注入临时 Token。直接使用该内置 Token 即可完成仓库级的读写认证,无需手动生成并维护 Personal Access Token (PAT),降低了密钥泄漏的风险。
  • force_orphan: true (重置提交历史)
    开启该参数后,每次部署都会在 gh-pages 分支创建一个无父节点的新提交(Orphan Commit),丢弃历史记录。静态资源分支通常只需要保留最新版本的产物,此举可避免 Git 仓库因累积大量构建产物历史(如无用的 Source Map)而导致存储体积急剧膨胀。

5. 执行链路总结

完成全部配置后,整体的工程发布链路如下:

  1. 开发者将源码 push 到项目的 main 分支。
  2. 触发 Gitea Actions,Runner 执行环境初始化、拉取源码、安装依赖并执行 npm run build 生成 dist 目录。
  3. actions-gh-pages 插件将 dist 目录作为根节点,强推至当前仓库的 gh-pages 分支。
  4. 推送行为触发 Gitea Webhook,通过预设密钥将事件推送至 deployer 的 8080 端口。
  5. deployer 验证 Webhook 请求合法后,通过浅克隆拉取 gh-pages 分支内容,写入共享数据卷。
  6. pages-nginx 实时读取挂载目录的最新静态文件,外部通过泛域名即可访问最新发布的站点。