Ubuntu 上使用 GitLab Webhooks 的完整实践
一 前置准备
二 在 GitLab 项目里添加 Webhook
三 在 Ubuntu 上搭建接收服务与验签示例
方案 A(PHP 最小可用示例,便于快速验证)
sudo apt update
sudo apt install -y nginx php-fpm
# 编辑站点配置,确保 .php 走 fastcgi,并暴露 /webhook 路径
sudo vim /etc/nginx/sites-enabled/default
# 在 server 段加入:
# location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php*.sock; }
# location /webhook { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php*.sock; }
sudo systemctl reload nginx
<?php
// 配置
$secret = 'YOUR_SECRET_TOKEN'; // 与 GitLab 一致
$repoPath = '/var/www/your-project'; // 项目绝对路径
$branch = 'main'; // 监听分支
$allowedIps = ['127.0.0.1', 'GITLAB_SERVER_IP']; // 建议限制来源 IP
// 简单来源 IP 校验(可选)
$clientIp = $_SERVER['REMOTE_ADDR'] ?? '';
if (!in_array($clientIp, $allowedIps, true)) {
http_response_code(403); exit('Forbidden');
}
// 读取请求体与签名(GitLab 使用 X-Gitlab-Token 或自定义 Header)
$payload = file_get_contents('php://input');
$event = $_SERVER['HTTP_X_GITLAB_EVENT'] ?? '';
$token = $_SERVER['HTTP_X_GITLAB_TOKEN'] ?? '';
// 验签
if ($token !== $secret) {
http_response_code(401); exit('Unauthorized');
}
// 只处理 push 事件并匹配分支
if ($event === 'Push Hook') {
$data = json_decode($payload, true);
$ref = $data['ref'] ?? '';
if ($ref === "refs/heads/{$branch}") {
// 注意:实际环境请使用部署用户与密钥,避免以 www-data 直接执行
$cmd = "cd {$repoPath} && git pull origin {$branch} 2>&1";
exec($cmd, $out, $ret);
file_put_contents('/tmp/webhook.log', date('Y-m-d H:i:s') . " [{$ref}] git pull => {$ret}\n" . implode("\n", $out) . "\n", FILE_APPEND);
}
}
http_response_code(200);
echo "OK";
# 允许 www-data 无密码执行 git(仅限 git 命令)
echo "www-data ALL=(ALL) NOPASSWD: /usr/bin/git" | sudo tee /etc/sudoers.d/webhook-git
sudo chmod 440 /etc/sudoers.d/webhook-git
方案 B(与 Jenkins 集成)
四 常见问题与排查