🚀 零依赖的 Gitea Webhook 服务,为 Astro 博客提供自动化构建部署
这个项目适合你,如果:
- ✅ 你使用 Astro 构建静态博客
- ✅ 你使用 Gitea 托管代码(自建 Git 服务)
- ✅ 博客服务器和 Gitea 在同一台机器
- ✅ 希望从多个地方(家里、公司)推送代码后自动构建
- ✅ 需要版本控制 + 自动部署的一体化方案
- ✅ 追求零依赖、简单易维护的解决方案
实际应用场景:
家里电脑 ──┐
├─→ Git Push → Gitea → Webhook → 自动构建 → 博客更新
公司电脑 ──┘
我的部署架构:
┌─────────────────────────────────────────────────┐
│ 服务器 (blog.example.com) │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Gitea │ │ Astro Blog │ │
│ │ :3000 │ │ :80/443 │ │
│ │ │ │ │ │
│ │ git仓库 │────────▶│ 构建产物 │ │
│ └──────┬───────┘ └──────────────┘ │
│ │ │
│ │ Webhook │
│ ▼ │
│ ┌──────────────┐ │
│ │ Webhook │ │
│ │ 服务 │ │
│ │ :28080 │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────┘
外部访问:
- Gitea: https://git.example.com
- 博客: https://blog.example.com
工作流程:
- 在家里的电脑写文章 →
git push到 Gitea - Gitea 触发 Webhook → 通知本地服务
- 本地服务自动执行:
git pull拉取最新代码pnpm install安装依赖pnpm build构建博客
- 博客自动更新完成 ✅
- ✅ 零依赖:仅使用 Node.js 原生模块,无需
npm install - ✅ 异步构建:立即响应 Gitea,不超时,显示绿色✅
- ✅ 签名验证:兼容 Gitea 格式的 HMAC-SHA256 签名
- ✅ systemd 管理:开机自启,崩溃自动重启
- ✅ 完整日志:journal + 文件双重日志
- ✅ 实时进度:通过
journalctl查看构建过程 - ✅ Nginx 集成:反向代理配置,支持 HTTPS
http- HTTP 服务器crypto- 签名验证child_process- 执行 Git/pnpm 命令fs- 文件系统操作
- Node.js 18+
- pnpm
- Git
- systemd (Linux)
- Nginx (可选,用于反向代理)
# 在本地电脑执行
scp -r gitea-astro-webhook root@your-server:/opt/# SSH 登录服务器
ssh root@your-server
# 进入项目目录
cd /opt/gitea-astro-webhook
# 复制配置文件
cp .env.example .env
# 编辑配置
nano .env配置示例:
# Webhook 服务端口
PORT=28080
# Gitea Webhook 密钥(下面会生成)
WEBHOOK_SECRET=your-webhook-secret-here
# 博客项目路径
BLOG_PATH=/home/wwwroot/blog
# Git 仓库地址(SSH 格式)
GIT_REPO=ssh://git@git.example.com:222/username/blog.git
# 监听的 Git 分支
GIT_BRANCH=main
# 日志级别:info | error
LOG_LEVEL=info生成密钥:
openssl rand -hex 32将生成的密钥粘贴到 WEBHOOK_SECRET。
# 修改服务文件中的路径(如果部署路径不同)
nano gitea-astro-webhook.service将以下三个路径改为实际路径:
WorkingDirectory=/opt/gitea-astro-webhookExecStart=/usr/bin/node /opt/gitea-astro-webhook/webhook.jsEnvironmentFile=/opt/gitea-astro-webhook/.env
# 安装服务
sudo cp gitea-astro-webhook.service /etc/systemd/system/
# 重新加载 systemd
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start gitea-astro-webhook
# 设置开机自启
sudo systemctl enable gitea-astro-webhook
# 查看服务状态
sudo systemctl status gitea-astro-webhook编辑你的 Nginx 配置文件:
nano /etc/nginx/conf.d/blog.example.com.conf添加以下配置:
location /webhook {
proxy_pass http://127.0.0.1:28080/webhook;
# 传递必要的请求头
proxy_pass_request_headers on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 传递 Gitea 签名头(重要)
proxy_set_header X-Gitea-Signature $http_x_gitea_signature;
proxy_set_header X-Gitea-Event $http_x_gitea_event;
# 增加超时时间(Astro 构建可能需要 2-5 分钟)
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
# 禁用缓冲(实时返回响应)
proxy_buffering off;
}测试并重启 Nginx:
# 测试配置
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx# 健康检查
curl http://localhost:28080/health
# 通过 Nginx 测试 Webhook 端点
curl https://blog.example.com/webhook
# 应该返回:
# {"message":"Gitea Webhook Endpoint","method":"POST required","usage":"Send POST request with Gitea webhook payload"}
# 查看日志
sudo journalctl -u gitea-astro-webhook -f在 Gitea 中:
- 打开仓库 → 设置 → Webhooks
- 添加 Webhook:
- URL:
https://blog.example.com/webhook - Content Type:
application/json - Secret: 粘贴
.env中的WEBHOOK_SECRET - Events: ✅ Push Events
- Branch:
main
- URL:
异步构建模式:
- Gitea 推送 webhook → 服务接收请求
- 验证签名(< 1秒)
- 立即返回 200 OK(Gitea 显示绿色✅)
- 后台异步执行构建:
- 拉取代码
- 安装依赖
- 构建博客
- 所有日志输出到 systemd journal
优点:
- ✅ Gitea 不会超时(立即响应)
- ✅ 构建不受影响(异步执行)
- ✅ 可查看实时日志(journalctl)
查看实时构建进度:
# 实时查看构建日志
sudo journalctl -u gitea-astro-webhook -f
# 查看最近 50 条日志
sudo journalctl -u gitea-astro-webhook -n 50
# 查看今天的日志
sudo journalctl -u gitea-astro-webhook --since today在本地电脑推送测试代码:
cd /path/to/your/blog
echo "test $(date)" > test.md
git add test.md
git commit -m "test: 测试自动部署"
git push origin main在服务器查看日志:
sudo journalctl -u gitea-astro-webhook -f应该看到:
[SUCCESS] 收到 push 事件: blog - main
[INFO] 开始拉取代码
[SUCCESS] 代码拉取完成
[INFO] 开始安装依赖: pnpm install
[SUCCESS] 依赖安装完成
[INFO] 开始构建博客: pnpm build
[SUCCESS] 博客构建完成
[SUCCESS] ✅ 部署完成!
在 Gitea 查看 webhook 状态,应该显示绿色✅(不再是超时警告)。
/opt/gitea-astro-webhook/
├── webhook.js # 主程序(零依赖)
├── package.json # 项目信息
├── .env # 环境变量配置
├── .env.example # 配置示例
├── gitea-astro-webhook.service # systemd 服务文件
├── nginx.conf.example # Nginx 反向代理配置
└── README.md # 本文档
# 重启服务
sudo systemctl restart gitea-astro-webhook
# 查看状态
sudo systemctl status gitea-astro-webhook
# 查看实时日志
sudo journalctl -u gitea-astro-webhook -f
# 查看最近 50 条日志
sudo journalctl -u gitea-astro-webhook -n 50
# 停止服务
sudo systemctl stop gitea-astro-webhook
# 查看文件日志
tail -f /opt/gitea-astro-webhook/logs/webhook.log本项目使用 Node.js 原生 crypto 模块进行签名验证:
import crypto from 'crypto';
// HMAC-SHA256 签名
const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
hmac.update(payload);
const expectedSignature = hmac.digest('hex');
// 验证(兼容 Gitea 格式)
const receivedSignature = signature.replace('sha256=', '').toLowerCase();
return crypto.timingSafeEqual(
Buffer.from(receivedSignature),
Buffer.from(expectedSignature)
);关键点:Gitea 的签名格式是纯 hex(不像 GitHub 有 sha256= 前缀),代码已自动处理。
问题:之前版本会因为 Astro 构建时间过长(2-5分钟)导致 Gitea 超时。
解决:✅ 已优化为异步构建模式,立即返回响应,不再超时。
问题:日志显示 签名验证失败
检查:
- Gitea Webhook 中的 Secret 是否正确
.env文件中的WEBHOOK_SECRET是否一致- 两边的密钥必须完全相同
重新配置密钥:
openssl rand -hex 32 # 生成新密钥
nano .env # 更新 WEBHOOK_SECRET
sudo systemctl restart gitea-astro-webhook # 重启服务然后在 Gitea 中更新 Webhook 的 Secret。
# 测试 SSH 连接
ssh -T -p 222 git@git.example.com
# 手动测试拉取
cd /home/wwwroot/blog
git fetch origin main# 检查 Node.js 版本
node --version # 需要 >= 18.0.0
# 手动启动测试
cd /opt/gitea-astro-webhook
node webhook.js
# 查看详细错误
sudo journalctl -u gitea-astro-webhook -n 50 --no-pager# 确保项目目录有正确的权限
sudo chown -R root:root /opt/gitea-astro-webhook
sudo chmod -R 755 /opt/gitea-astro-webhook| 特性 | 本项目 | GitHub Actions | GitLab CI |
|---|---|---|---|
| 适用场景 | Gitea + 自托管 | GitHub | GitLab |
| 外部依赖 | ❌ 零依赖 | ✅ 需要 GitHub | ✅ 需要 GitLab |
| 构建位置 | 本地服务器 | 云端 | 云端/本地 |
| 响应速度 | < 1秒 | 1-2分钟 | 1-2分钟 |
| 网络需求 | 内网即可 | 需外网 | 需外网 |
| 成本 | 免费 | 免费额度限制 | 免费额度限制 |
| 配置复杂度 | ⭐ 简单 | ⭐⭐⭐ 中等 | ⭐⭐⭐ 复杂 |
- 适合自托管:如果你已经自建 Gitea,这个方案完美契合
- 零依赖:无需 npm install,部署简单,维护成本低
- 即时响应:异步构建模式,Gitea 立即收到成功响应
- 透明可控:所有代码都在本地,完全掌控构建过程
- 成本低:无需 CI/CD 云服务,一台服务器搞定所有
MIT License
欢迎提交 Issue 和 Pull Request!
如果这个项目对你有帮助,请给个 Star ⭐
问题反馈:请提交 Issue
参考链接:
如果这个项目对你有帮助,欢迎请我喝杯咖啡:
Made with ❤️ by GOWAH
