Getting Started¶
This guide walks you through installing Hookaido and running your first webhook ingress queue.
Install¶
Pre-built binary (no Go required):
Download the latest binary for your platform from GitHub Releases.
Build from source (requires Go 1.26+):
Docker:
See Docker Quickstart for a full Docker / Docker Compose guide.
Verify:
Minimal Pull-Mode Setup¶
Pull mode is the recommended default: Hookaido receives webhooks in the DMZ, and your internal workers pull messages via outbound-only connections.
1. Create a Hookaidofile¶
ingress {
listen :8080
}
pull_api {
auth token env:HOOKAIDO_PULL_TOKEN
}
/webhooks/github {
auth hmac {
provider github
secret env:HOOKAIDO_INGRESS_SECRET
}
pull { path /pull/github }
}
This config:
- Listens for incoming webhooks on
:8080 - Exposes a Pull API on
:9443(default) with token authentication - Routes
POST /webhooks/githubthrough GitHub signature verification (X-Hub-Signature-256), then enqueues
2. Set Environment Variables¶
export HOOKAIDO_PULL_TOKEN="your-pull-secret"
export HOOKAIDO_INGRESS_SECRET="your-hmac-secret" # the "Secret" set on the GitHub webhook
For local development, use a dotenv file instead:
3. Start Hookaido¶
With dotenv:
Hookaido starts three listeners:
- Ingress on
:8080— receives webhooks - Pull API on
:9443— workers consume from here - Admin API on
127.0.0.1:2019— health checks, DLQ management
4. Send a Test Webhook¶
Sign the body the way GitHub does (sha256= + hex HMAC-SHA256 of the raw body):
BODY='{"action": "push", "ref": "refs/heads/main"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$HOOKAIDO_INGRESS_SECRET" | awk '{print $NF}')
curl -X POST http://localhost:8080/webhooks/github \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: push" \
-H "X-Hub-Signature-256: sha256=$SIG" \
-d "$BODY"
Hookaido answers 202 Accepted once the event is queued. A missing or wrong signature gets 401. Once a real GitHub webhook points at this URL with the same secret, its deliveries verify the same way.
5. Consume Messages¶
Your worker polls the Pull API:
# Dequeue a batch
curl -X POST http://localhost:9443/pull/github/dequeue \
-H "Authorization: Bearer devtoken" \
-H "Content-Type: application/json" \
-d '{"batch": 10, "lease_ttl": "30s"}'
Response:
{
"items": [
{
"id": "evt_abc123",
"lease_id": "lease_xyz",
"route": "/webhooks/github",
"target": "pull",
"payload_b64": "eyJhY3Rpb24iOiAicHVzaCJ9",
"headers": { "Content-Type": "application/json" },
"received_at": "2026-02-09T10:00:00Z",
"attempt": 1
}
]
}
After processing, acknowledge:
curl -X POST http://localhost:9443/pull/github/ack \
-H "Authorization: Bearer devtoken" \
-H "Content-Type: application/json" \
-d '{"lease_id": "lease_xyz"}'
Or reject (requeue with delay):
curl -X POST http://localhost:9443/pull/github/nack \
-H "Authorization: Bearer devtoken" \
-H "Content-Type: application/json" \
-d '{"lease_id": "lease_xyz", "delay": "5s"}'
Minimal Push-Mode Setup¶
In push mode, Hookaido delivers webhooks directly to your internal endpoints:
No Pull API is needed — Hookaido handles retry, backoff, and (optional) outbound signing. See Delivery (Push) for details.
Minimal Exec-Mode Setup¶
Exec mode runs a local script for each webhook — no HTTP server needed on the receiving end:
/webhooks/github {
auth hmac {
provider github
secret env:GITHUB_WEBHOOK_SECRET
}
deliver exec "./handle-webhook.sh" {
timeout 30s
}
}
Create a handler script:
#!/usr/bin/env bash
# handle-webhook.sh — payload arrives on stdin
PAYLOAD=$(cat)
echo "Received: $(echo "$PAYLOAD" | jq -r '.action // .ref')" >&2
# Exit 0 = ack, non-zero = retry
Start Hookaido:
export GITHUB_WEBHOOK_SECRET="your-github-secret"
chmod +x handle-webhook.sh
./hookaido run --config ./Hookaidofile --db ./.data/hookaido.db
The script runs once per webhook event. Exit code 0 acknowledges the message; any other exit code triggers a retry. See Subprocess Execution for exit code details and environment variables.
Validate Your Config¶
Before starting:
Format (canonical style, idempotent):
Check Health¶
curl http://127.0.0.1:2019/healthz
# Detailed diagnostics:
curl http://127.0.0.1:2019/healthz?details=1
CLI Reference¶
| Command | Description |
|---|---|
hookaido run |
Start the server |
hookaido config fmt |
Format the Hookaidofile |
hookaido config validate |
Validate config (exit code 0/1) |
hookaido mcp serve |
Start MCP server (AI tooling) |
hookaido config diff |
Show differences between two config files |
hookaido verify-release |
Verify release artifact checksums and signatures |
hookaido version |
Print version |
hookaido run Flags¶
| Flag | Default | Description |
|---|---|---|
--config |
./Hookaidofile |
Path to config file |
--db |
./hookaido.db |
Path to SQLite database. The container image overrides this with /app/.data/hookaido.db, which is the declared volume |
--postgres-dsn |
— | PostgreSQL DSN (when queue.backend is postgres) |
--pid-file |
— | Write PID file (enables SIGHUP reload) |
--watch |
false |
Hot-reload on config file changes |
--watch-interval |
— | With --watch, also poll the config for content changes at this interval (min 1s). Needed when the config is a single-file bind mount — see Hot Reload |
--log-level |
info |
Runtime log level |
--dotenv |
— | Load environment variables from file |
Next Steps¶
- Configuration Reference — full DSL documentation
- Deployment Modes — pull vs push, DMZ topology
- Ingress — route matching and authentication
- Pull API — consumer protocol details
- Docker Quickstart — run with Docker / Docker Compose
- Security — TLS, HMAC, SSRF protection
- Observability — logging, metrics, tracing