背景

之前每次更新博客都需要手动SSH到VPS执行部署脚本,效率低下。通过GitHub Webhook + Flask服务实现了自动化部署,推送代码后自动触发VPS更新。

架构设计

1
GitHub Push → Webhook → Nginx → Flask服务 → 执行deploy.sh → 更新博客

核心组件:

  • Flask Webhook服务: 接收GitHub推送事件
  • Nginx反向代理: 提供HTTPS访问和安全控制
  • systemd服务: 保证webhook服务稳定运行
  • deploy.sh脚本: 现有的部署脚本

实施步骤

1. 安装Webhook服务

1
2
3
4
cd /garlicspace/site
git pull origin main
chmod +x webhook/install.sh
./webhook/install.sh

安装脚本会自动:

  • 安装Python依赖(Flask)
  • 生成webhook密钥
  • 配置systemd服务
  • 设置文件权限

重要: 保存安装脚本输出的WEBHOOK_SECRET,后续GitHub配置需要。

2. 配置sudoers权限

编辑sudoers配置:

1
sudo visudo

添加以下权限:

1
2
3
4
5
# Webhook自动部署权限
deploy ALL=(ALL) NOPASSWD: /garlicspace/site/deploy.sh

# 现有部署脚本权限
deploy ALL=(ALL) NOPASSWD: /usr/bin/rsync, /bin/chmod, /usr/bin/find, /bin/mkdir, /usr/bin/systemctl, /usr/bin/cp, /usr/bin/tee, /usr/bin/chown

3. 配置Nginx代理

编辑Nginx配置文件:

1
sudo nano /etc/nginx/conf.d/garlicspace.com.conf

在server块中添加:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Webhook代理配置
location /webhook {
    proxy_pass http://127.0.0.1:5000;
    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;
    
    # GitHub IP白名单(可选)
    allow 140.82.112.0/20;
    allow 185.199.108.0/22;
    allow 192.30.252.0/22;
    allow 143.55.64.0/20;
    deny all;
}

重载Nginx:

1
sudo nginx -t && sudo nginx -s reload

4. 配置GitHub Webhook

  1. 进入GitHub仓库 → SettingsWebhooks
  2. 点击 Add webhook
  3. 配置:
    • Payload URL: https://garlicspace.com/webhook
    • Content type: application/json
    • Secret: 使用安装脚本生成的密钥
    • Events: 选择 Just the push event
  4. 点击 Add webhook

5. 测试自动部署

推送测试提交:

1
2
3
git add .
git commit -m "test: webhook auto deploy"
git push origin main

查看部署日志:

1
2
3
4
5
# 查看webhook服务日志
sudo journalctl -u blog-webhook -f

# 查看webhook日志文件
tail -f /opt/blog-webhook/webhook.log

常见问题

1. 服务启动失败

问题: status=217/USER 原因: CentOS 7没有www-data用户 解决: 使用deploy用户运行服务(已在配置中修复)

2. Python模块缺失

问题: ModuleNotFoundError: No module named 'flask' 解决:

1
sudo pip3 install flask python-dotenv

3. 日志文件权限错误

问题: PermissionError: /var/log/blog-webhook.log 解决: 日志已改为用户目录 /opt/blog-webhook/webhook.log

4. Python 3.6兼容性

问题: unexpected keyword argument 'capture_output''text' 解决: 使用stdout/stderruniversal_newlines参数(已修复)

5. 部署脚本权限不足

问题: deploy用户无法执行deploy.sh 解决: 配置sudoers允许无密码执行deploy.sh

6. Hugo构建错误

问题: frontmatter中的转义字符导致构建失败 解决: 移除不必要的转义字符(如 \* 改为 *

监控和维护

查看服务状态

1
sudo systemctl status blog-webhook

查看实时日志

1
sudo journalctl -u blog-webhook -f

重启服务

1
sudo systemctl restart blog-webhook

健康检查

1
curl https://garlicspace.com/webhook/health

安全特性

  1. HMAC签名验证: 验证请求来自GitHub
  2. GitHub IP白名单: 限制访问来源
  3. 分支过滤: 只处理main分支推送
  4. 超时保护: 部署超时自动终止
  5. 错误日志: 完整的错误追踪

技术栈

  • Python 3.6+: Flask webhook服务
  • Flask: Web框架
  • systemd: 服务管理
  • Nginx: 反向代理
  • CentOS 7: 服务器环境
  • Hugo: 静态网站生成器

文件结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/opt/blog-webhook/
├── webhook_server.py    # Flask服务主程序
├── .env                 # 环境变量配置
└── webhook.log          # 运行日志

/garlicspace/site/
├── webhook/
│   ├── webhook_server.py
│   ├── blog-webhook.service
│   ├── nginx-webhook.conf
│   ├── install.sh
│   └── README.md
└── deploy.sh            # 部署脚本

性能优化建议

  1. 使用生产WSGI服务器: 当前使用Flask开发服务器,建议升级为Gunicorn或uWSGI
  2. 添加部署队列: 避免并发部署冲突
  3. 实现部署锁: 防止重复部署
  4. 添加通知系统: 集成Telegram/邮件通知部署结果

总结

通过GitHub Webhook实现了博客的自动化部署,大大提升了工作效率。整个系统稳定可靠,配置简单,适合个人博客和小型项目使用。

部署效果: 从推送代码到博客更新,全程自动化,耗时约30秒。


最后更新: 2026-02-23