背景
之前每次更新博客都需要手动SSH到VPS执行部署脚本,效率低下。通过GitHub Webhook + Flask服务实现了自动化部署,推送代码后自动触发VPS更新。
架构设计
| |
核心组件:
- Flask Webhook服务: 接收GitHub推送事件
- Nginx反向代理: 提供HTTPS访问和安全控制
- systemd服务: 保证webhook服务稳定运行
- deploy.sh脚本: 现有的部署脚本
实施步骤
1. 安装Webhook服务
| |
安装脚本会自动:
- 安装Python依赖(Flask)
- 生成webhook密钥
- 配置systemd服务
- 设置文件权限
重要: 保存安装脚本输出的WEBHOOK_SECRET,后续GitHub配置需要。
2. 配置sudoers权限
编辑sudoers配置:
| |
添加以下权限:
| |
3. 配置Nginx代理
编辑Nginx配置文件:
| |
在server块中添加:
| |
重载Nginx:
| |
4. 配置GitHub Webhook
- 进入GitHub仓库 → Settings → Webhooks
- 点击 Add webhook
- 配置:
- Payload URL:
https://garlicspace.com/webhook - Content type:
application/json - Secret: 使用安装脚本生成的密钥
- Events: 选择
Just the push event
- Payload URL:
- 点击 Add webhook
5. 测试自动部署
推送测试提交:
| |
查看部署日志:
| |
常见问题
1. 服务启动失败
问题: status=217/USER
原因: CentOS 7没有www-data用户
解决: 使用deploy用户运行服务(已在配置中修复)
2. Python模块缺失
问题: ModuleNotFoundError: No module named 'flask'
解决:
| |
3. 日志文件权限错误
问题: PermissionError: /var/log/blog-webhook.log
解决: 日志已改为用户目录 /opt/blog-webhook/webhook.log
4. Python 3.6兼容性
问题: unexpected keyword argument 'capture_output' 或 'text'
解决: 使用stdout/stderr和universal_newlines参数(已修复)
5. 部署脚本权限不足
问题: deploy用户无法执行deploy.sh 解决: 配置sudoers允许无密码执行deploy.sh
6. Hugo构建错误
问题: frontmatter中的转义字符导致构建失败
解决: 移除不必要的转义字符(如 \* 改为 *)
监控和维护
查看服务状态
| |
查看实时日志
| |
重启服务
| |
健康检查
| |
安全特性
- HMAC签名验证: 验证请求来自GitHub
- GitHub IP白名单: 限制访问来源
- 分支过滤: 只处理main分支推送
- 超时保护: 部署超时自动终止
- 错误日志: 完整的错误追踪
技术栈
- Python 3.6+: Flask webhook服务
- Flask: Web框架
- systemd: 服务管理
- Nginx: 反向代理
- CentOS 7: 服务器环境
- Hugo: 静态网站生成器
文件结构
| |
性能优化建议
- 使用生产WSGI服务器: 当前使用Flask开发服务器,建议升级为Gunicorn或uWSGI
- 添加部署队列: 避免并发部署冲突
- 实现部署锁: 防止重复部署
- 添加通知系统: 集成Telegram/邮件通知部署结果
总结
通过GitHub Webhook实现了博客的自动化部署,大大提升了工作效率。整个系统稳定可靠,配置简单,适合个人博客和小型项目使用。
部署效果: 从推送代码到博客更新,全程自动化,耗时约30秒。
最后更新: 2026-02-23