I have a webhook configured in GitLab. When I trigger it using the "Test" function, it shows a status code 200. On the target machine a systemd service is listening for that webhook, and is supposed to execute a build script. If I run the script directly, all is fine. How can I set up the webhook service so that it receives the notification from GitLab?
This is how I set the service up in Ansible:
- name: Create the webhooks service
copy:
dest: /etc/systemd/system/webhook.service
content: |
[Unit]
Description=Webhooks
[Service]
ExecStart=/usr/bin/webhook -secure \
-cert /etc/letsencrypt/live/my-project.mywebsite.com/fullchain.pem \
-key /etc/letsencrypt/live/my-project.mywebsite.com/privkey.pem \
-hooks /home/myuser/webhooks/hooks.json \
-hotreload \
-verbose
WorkingDirectory=/home/myuser/webhooks
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
- name: Enable the webhooks service
command: systemctl enable webhook.service
- name: (Re-)start the webhooks service
command: systemctl restart webhook.service
This is my /home/myuser/webhooks/hooks.json
:
[{
"id": "my-repository",
"execute-command": "/home/myuser/webhooks/my-repository/deploy.sh",
"command-working-directory": "/home/myuser/my-repository/",
"response-message": "Executing deploy script...",
"trigger-rule": {
"match": {
"type": "payload-hmac-sha1",
"secret":"<WEBHOOK_SECRET_LIKE_IN_GITLAB>",
"parameter": {
"source": "header",
"name": "X-Hub-Signature"
}
}
}
}]
I can confirm that the service is listening on the correct port, (9000 is default for webhooks):
myuser@mymachine:~$ sudo lsof -i -P -n | grep 9000
webhook 609262 root 6u IPv6 1589700 0t0 TCP *:9000 (LISTEN)
Both the GitLab server and the target machine are on the same private Hetzner network. GitLab is on 10.0.2.1
, the target machine is on 10.0.3.1
.
The systemd service is running:
myuser@mymachine:~$ sudo systemctl status webhook.service
● webhook.service - Webhooks
Loaded: loaded (/etc/systemd/system/webhook.service; enabled; preset: enabled)
Active: active (running) since Tue 2024-10-08 18:42:34 UTC; 23s ago
Main PID: 637049 (webhook)
Tasks: 9 (limit: 18692)
Memory: 2.1M (peak: 2.4M)
CPU: 8ms
CGroup: /system.slice/webhook.service
└─637049 /usr/bin/webhook -secure -cert /etc/letsencrypt/live/my-project.mywebsite.com/fullchain.pem -key /etc/letsencrypt/live/my-project.mywebsite.com/privkey.pem -hooks >
Oct 08 18:42:34 my-project.mywebsite.com systemd[1]: Started webhook.service - Webhooks.
Oct 08 18:42:34 my-project.mywebsite.com webhook[637049]: [webhook] 2024/10/08 18:42:34 version 2.8.0 starting
Oct 08 18:42:34 my-project.mywebsite.com webhook[637049]: [webhook] 2024/10/08 18:42:34 setting up os signal watcher
Oct 08 18:42:34 my-project.mywebsite.com webhook[637049]: [webhook] 2024/10/08 18:42:34 attempting to load hooks from /home/myuser/webhooks/hooks.json
Oct 08 18:42:34 my-project.mywebsite.com webhook[637049]: [webhook] 2024/10/08 18:42:34 found 1 hook(s) in file
Oct 08 18:42:34 my-project.mywebsite.com webhook[637049]: [webhook] 2024/10/08 18:42:34 loaded: my-repository
Oct 08 18:42:34 my-project.mywebsite.com webhook[637049]: [webhook] 2024/10/08 18:42:34 os signal watcher ready
Oct 08 18:42:34 my-project.mywebsite.com webhook[637049]: [webhook] 2024/10/08 18:42:34 setting up file watcher for /home/myuser/webhooks/hooks.json
Oct 08 18:42:34 my-project.mywebsite.com webhook[637049]: [webhook] 2024/10/08 18:42:34 serving hooks on https://0.0.0.0:9000/hooks/{id}
This /home/myuser/webhooks/hooks.json
would only work for GitHub. GitLab doesn't send the X-Hub-Signature
header, and in fact, doesn't seem to sign its responses. Instead, it just sends the secret in the header, and webhook
then compares it to the one in the json. The correct hook definition for GitLab looks like this:
[{
"id": "my-repository",
"execute-command": "/home/myuser/webhooks/my-repository/deploy.sh",
"command-working-directory": "/home/myuser/my-repository/",
"response-message": "Executing deploy script...",
"trigger-rule": {
"match": {
"type": "value",
"parameter": {
"source": "header",
"name": "X-Gitlab-Token"
},
"value": "<WEBHOOK_SECRET_LIKE_IN_GITLAB>"
}
}
}]
Also, I added these two flags in the service definition:
tls-min-version 1.3
and http-methods POST
. The former is fine, as I know that GitLab supports TLS v1.3 and I know my machine does as well, the latter since I only have one webhook and it uses POST.