# GitHub Webhook自动部署Hugo博客到VPS
Date: 2026-02-23


## 背景

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

## 架构设计

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

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

## 实施步骤

### 1. 安装Webhook服务

```bash
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配置：
```bash
sudo visudo
```

添加以下权限：
```bash
# 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配置文件：
```bash
sudo nano /etc/nginx/conf.d/garlicspace.com.conf
```

在server块中添加：
```nginx
# 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：
```bash
sudo nginx -t && sudo nginx -s reload
```

### 4. 配置GitHub Webhook

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

### 5. 测试自动部署

推送测试提交：
```bash
git add .
git commit -m "test: webhook auto deploy"
git push origin main
```

查看部署日志：
```bash
# 查看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'`
**解决**:
```bash
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/stderr`和`universal_newlines`参数（已修复）

### 5. 部署脚本权限不足

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

### 6. Hugo构建错误

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

## 监控和维护

### 查看服务状态
```bash
sudo systemctl status blog-webhook
```

### 查看实时日志
```bash
sudo journalctl -u blog-webhook -f
```

### 重启服务
```bash
sudo systemctl restart blog-webhook
```

### 健康检查
```bash
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**: 静态网站生成器

## 文件结构

```
/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*

