A lightweight server that listens for GitHub Webhook events and executes commands when specific conditions are matched. Useful for automated deployments, CI triggers, and other GitHub-driven workflows.
npm install -g github-webhookgithub-webhook \
--port=9999 \
--path=/webhook \
--secret=mygithubsecret \
--rule='push:ref == "refs/heads/master" && repository.name == "myrepo":./deploy.sh'Then configure your GitHub repository's webhook settings to point to http://yourserver:9999/webhook with the matching secret.
You can configure github-webhook via command-line arguments or a JSON config file (or both - command-line overrides the config file).
github-webhook \
--config=/etc/github-webhook.json \
--port=9999 \
--path=/webhook \
--secret=mygithubsecret \
--log=/var/log/webhook.log \
--rule='push:ref == "refs/heads/master":./deploy.sh'{
"port": 9999,
"path": "/webhook",
"secret": "mygithubsecret",
"log": "/var/log/webhook.log",
"rules": [
{
"event": "push",
"match": "ref == \"refs/heads/master\" && repository.full_name == \"myuser/myrepo\"",
"exec": "/var/www/deploy.sh"
}
]
}| Option | Required | Description |
|---|---|---|
port |
Yes | Port to listen on (also respects PORT env var) |
path |
Yes | URL path to receive webhooks (e.g., /webhook) |
secret |
Yes | Webhook secret for payload verification (configure the same value in GitHub) |
host |
No | Bind to a specific host/IP address |
log |
No | Log file path, or stdout/stderr for console output |
rules |
No | Array of rules to match and execute (see below) |
Rules define what commands to execute when specific webhook events are received.
| Property | Description |
|---|---|
event |
GitHub event type to match (push, pull_request, issues, etc.). Use * to match all events. See GitHub Webhooks documentation for available events. |
match |
Expression to match against the webhook payload. Uses matchme syntax. |
exec |
Command to execute. A string runs via sh -c "...". An array executes directly (first element is the command, rest are arguments). |
Rules can be specified on the command line as --rule 'event:match:exec':
--rule 'push:ref == "refs/heads/master":./deploy.sh'Commands receive the entire webhook payload as environment variables with a gh_ prefix:
gh_ref- The git ref (e.g.,refs/heads/master)gh_branch- The branch name (extracted from ref for convenience)gh_repository_name- Repository namegh_repository_full_name- Full repository name (e.g.,owner/repo)gh_sender_login- Username of the person who triggered the event- ... and all other payload fields
Nested objects become underscore-separated (e.g., gh_repository_owner_login).
Deploy on push to master:
{
"event": "push",
"match": "ref == \"refs/heads/master\" && repository.full_name == \"myuser/myrepo\"",
"exec": "/var/www/deploy.sh"
}Run tests on pull request:
{
"event": "pull_request",
"match": "action == \"opened\" || action == \"synchronize\"",
"exec": ["./run-tests.sh", "--pr"]
}Log all events:
{
"event": "*",
"match": "true",
"exec": "echo \"Received $gh_event\" >> /var/log/webhooks.log"
}Create /etc/systemd/system/github-webhook.service:
[Unit]
Description=GitHub Webhook Server
After=network.target
[Service]
Type=simple
User=www-data
ExecStart=/usr/bin/github-webhook --config /etc/github-webhook.json
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetThen enable and start:
sudo systemctl daemon-reload
sudo systemctl enable github-webhook
sudo systemctl start github-webhook
sudo systemctl status github-webhookView logs:
sudo journalctl -u github-webhook -fFor production, run github-webhook behind nginx or another reverse proxy that handles TLS:
location /webhook {
proxy_pass http://127.0.0.1:9999;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}Then configure github-webhook with --host=127.0.0.1 to only accept local connections.
import webhook from 'github-webhook'
const server = webhook({
port: 9999,
path: '/webhook',
secret: 'mygithubsecret',
rules: [
{
event: 'push',
match: 'ref == "refs/heads/master"',
exec: './deploy.sh'
}
]
})
server.listen(9999, () => {
console.log('Webhook server listening on port 9999')
})The function returns an http.Server instance with an attached webhookHandler for custom event handling:
server.webhookHandler.on('push', (event) => {
console.log('Push event:', event.payload)
})Enable debug output with the DEBUG environment variable:
DEBUG=github-webhook:* github-webhook --config /etc/github-webhook.jsongithub-webhook is powered by github-webhook-handler.
github-webhook is Copyright (c) 2015 Rod Vagg and licensed under the MIT License. All rights not explicitly granted in the MIT License are reserved. See the included LICENSE.md file for more details.