Webhook 自动部署代码完整教程
Webhook 是实现代码自动部署的轻量级方案。当你向 Git 仓库推送代码时,代码托管平台会向你配置的 URL 发送 HTTP 请求,搬瓦工 VPS 上的 Webhook 服务器接收到请求后自动执行部署脚本。本文将介绍如何实现这一流程。购买搬瓦工使用优惠码 NODESEEK2026 享 6.77% 折扣。
一、工作原理
自动部署流程:开发者推送代码到 GitHub/Gitea → 平台发送 Webhook HTTP POST → VPS 上的 Webhook 服务器接收请求 → 验证签名 → 执行部署脚本(git pull、构建、重启服务)。
二、方案一:使用 webhook 工具
webhook 是一个用 Go 编写的轻量级 Webhook 服务器,非常适合在搬瓦工 VPS 上运行。
# 安装 webhook
apt update && apt install webhook -y
# 或下载二进制
wget https://github.com/adnanh/webhook/releases/download/2.8.1/webhook-linux-amd64.tar.gz
tar -xzf webhook-linux-amd64.tar.gz
mv webhook-linux-amd64/webhook /usr/local/bin/
配置 Webhook
# 创建配置文件 /etc/webhook/hooks.json
mkdir -p /etc/webhook
cat > /etc/webhook/hooks.json << 'EOF'
[
{
"id": "deploy-website",
"execute-command": "/opt/scripts/deploy.sh",
"command-working-directory": "/opt/my-website",
"response-message": "Deployment started",
"trigger-rule": {
"and": [
{
"match": {
"type": "payload-hmac-sha256",
"secret": "your-webhook-secret",
"parameter": {
"source": "header",
"name": "X-Hub-Signature-256"
}
}
},
{
"match": {
"type": "value",
"value": "refs/heads/main",
"parameter": {
"source": "payload",
"name": "ref"
}
}
}
]
}
}
]
EOF
编写部署脚本
# /opt/scripts/deploy.sh
cat > /opt/scripts/deploy.sh << 'EOF'
#!/bin/bash
set -e
LOG_FILE="/var/log/deploy.log"
DEPLOY_DIR="/opt/my-website"
echo "$(date) - Starting deployment..." >> $LOG_FILE
cd $DEPLOY_DIR
# 拉取最新代码
git pull origin main >> $LOG_FILE 2>&1
# Node.js 项目
npm install --production >> $LOG_FILE 2>&1
npm run build >> $LOG_FILE 2>&1
pm2 restart my-app >> $LOG_FILE 2>&1
# 或 Python 项目
# source .venv/bin/activate
# pip install -r requirements.txt
# systemctl restart my-app
echo "$(date) - Deployment completed!" >> $LOG_FILE
EOF
chmod +x /opt/scripts/deploy.sh
启动 Webhook 服务
# 测试运行
webhook -hooks /etc/webhook/hooks.json -verbose -port 9000
# Systemd 服务
cat > /etc/systemd/system/webhook.service << 'EOF'
[Unit]
Description=Webhook Server
After=network.target
[Service]
ExecStart=/usr/local/bin/webhook -hooks /etc/webhook/hooks.json -port 9000
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable webhook && systemctl start webhook
三、方案二:简易 Python Webhook
# /opt/scripts/webhook-server.py
from http.server import HTTPServer, BaseHTTPRequestHandler
import hmac, hashlib, subprocess, json
SECRET = b'your-webhook-secret'
class WebhookHandler(BaseHTTPRequestHandler):
def do_POST(self):
content_length = int(self.headers['Content-Length'])
payload = self.rfile.read(content_length)
# 验证签名
signature = self.headers.get('X-Hub-Signature-256', '')
expected = 'sha256=' + hmac.new(SECRET, payload, hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, expected):
self.send_response(403)
self.end_headers()
return
# 检查是否是 main 分支
data = json.loads(payload)
if data.get('ref') == 'refs/heads/main':
subprocess.Popen(['/opt/scripts/deploy.sh'])
self.send_response(200)
self.end_headers()
self.wfile.write(b'OK')
HTTPServer(('0.0.0.0', 9000), WebhookHandler).serve_forever()
四、在 GitHub/Gitea 配置 Webhook
在代码仓库的 Settings → Webhooks 中添加:
- Payload URL:
http://你的VPS-IP:9000/hooks/deploy-website - Content type:application/json
- Secret:your-webhook-secret(与服务端一致)
- Events:Just the push event
建议使用 Nginx 反向代理并配置 HTTPS,避免 Secret 在网络上明文传输。
五、Nginx 反向代理配置
server {
listen 443 ssl;
server_name webhook.example.com;
ssl_certificate /etc/letsencrypt/live/webhook.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/webhook.example.com/privkey.pem;
location /hooks/ {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
六、安全最佳实践
- 始终验证 Webhook 签名,防止伪造请求。
- 使用 HTTPS 传输,保护 Secret 不被截获。
- 部署脚本使用低权限用户运行,避免 root。
- 限制 Webhook 端口仅接受来自 GitHub/Gitea IP 的请求。
- 记录部署日志,方便排查问题。
总结
Webhook 自动部署是比完整 CI/CD 系统更轻量的方案,适合个人项目和小团队。对于更复杂的部署需求,可以参考 Jenkins vs GitLab CI 对比。自建 Git 服务请参考 Git 服务器教程 和 Gitea 部署教程。选购搬瓦工请访问 全部方案,使用优惠码 NODESEEK2026 享 6.77% 折扣,通过 bwh81.net 进入官网。