Listen to the podcast version:
My goal is to create a simple webhook that will run a custom Bash script on every POST request.
The webhook must be secured with a token.
What is a Webhook?
In short: A webhook is an automatic notification sent from one system to another when a specific event occurs.
Think of it like a doorbell: when someone presses the button (an event happens), the bell rings (a message is sent) to let you know.
In webhooks, when an event (like a new commit to a code repository) happens, a message (usually an HTTP request) is sent to a specific web address (URL) you set up. This lets your server know right away, so it can do something automatically, like start a deployment.
Setting Up a Webhook
To keep it simple, I will use a lightweight webhook server, written in Go:
webhook (Github repo).
The documentation and examples are available here.
Webhook Installation
The webhook server is available as an apt package.
sudo apt update && sudo apt upgrade
sudo apt install webhook
Configure a Webhook Endpoint
sudo mkdir -p /etc/webhook
sudo vi /etc/webhook/hooks.json
Now, let’s create a simple hook that will run only if the provided token is correct:
[
{
"id": "test-hook",
"execute-command": "/usr/local/bin/webhook/test-hook.sh",
"response-message": "Executing test webhook...",
"trigger-rule": {
"match": {
"type": "value",
"value": "secret-token-value",
"parameter": {
"source": "url",
"name": "token"
}
}
}
}
]
Create a Sample Script to Be Executed
For demonstration I will create a simple script, that will log a datetime of it’s execution.
sudo mkdir -p /usr/local/bin/webhook
sudo vi /usr/local/bin/webhook/test-hook.sh
#!/bin/bash
LOG_FILE="/var/log/webhook_test.log"
echo "[Webhook Triggered] $(date '+%F %T')" >> "$LOG_FILE"
Make script executable:
sudo chmod 750 /usr/local/bin/webhook/test-hook.sh
Run the Webhook
The webhook service runs on port 9000 by default. If you want to use a different port, specify the -p port_number
option.
webhook -hooks /etc/webhook/hooks.json -verbose
Create a systemd webhook.service
To make it persistent with systemd you have to create a service unit.
sudo vi /etc/systemd/system/webhook.service
[Unit]
Description=Webhook Listener
After=network.target
[Service]
ExecStart=/usr/bin/webhook -hooks /etc/webhook/hooks.json -verbose
Restart=always
[Install]
WantedBy=multi-user.target
Activate a webhook service:
sudo systemctl daemon-reload
sudo systemctl enable --now webhook.service
sudo systemctl start webhook.service
Configure an Nginx Server
Add a simple Nginx proxy configuration, to pass request to port 9000.
sudo vi /etc/nginx/sites-available/webhook
server {
server_name webhook.example.com;
listen 80;
return 302 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name webhook.example.com;
ssl_certificate /etc/nginx/ssl/webhook.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/webhook.example.com.key;
access_log /var/log/nginx/webhook.access.log;
error_log /var/log/nginx/webhook.error.log;
location / {
proxy_pass http://127.0.0.1:9000/hooks/;
proxy_http_version 1.1;
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;
# Optional: Prevent POST flooding
limit_except POST {
deny all;
}
}
}
Now, create a symbolic link to enable the site, and test the new configuration:
sudo ln -s /etc/nginx/sites-available/webhook /etc/nginx/sites-enabled/
sudo nginx -t
If nginx does not report any errors, reload:
sudo nginx -s reload
Webhook Testing
Call the hook with the token:
curl -X POST "https://webhook.example.com/test-hook?token=secret-token-value"
You should receive a response from the server:Executing test webhook...
This confirms that the script execution was triggered successfully.
If you look into the log file, you should see the script output:[Webhook Triggered] 2025-07-14 12:00:02
Summary
In this tutorial, you learned how to set up a secure webhook on an Ubuntu server using the lightweight webhook server.
You configured a webhook endpoint protected by a token, created a Bash script to be triggered by incoming POST requests, and set up systemd to run the webhook service persistently.
Additionally, you configured Nginx as a reverse proxy to securely expose your webhook endpoint over HTTPS.
Finally, you tested the setup to ensure everything works as expected.
This approach provides a simple, secure, and automated way to trigger custom scripts on your server in response to external events.
👍 Good job!