Config-driven webhook gateway. Receive HTTP webhooks, validate them, and route messages to queues.
External service (GitHub, Stripe, Coolify, etc.)
→ POST https://hooks.yourdomain.com/github/push
→ Hookpipe matches route from config
→ validates request (signature, bearer token)
→ wraps in message envelope
→ produces to sink (RabbitMQ, Kafka, SQS, HTTP, stdout)
→ returns 202 Accepted
docker run -p 8080:8080 \
-v ./config:/app/config \
-e RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672 \
ghcr.io/runax-software/hookpipe:latestgit clone https://github.com/runax-software/runax-hookpipe.git
cd runax-hookpipe
cp .env.example .env
# Start RabbitMQ + Kafka (optional)
docker compose up -d
dotnet run --project src/Hookpipe.APIcurl -X POST http://localhost:8080/test/webhook \
-H "Content-Type: application/json" \
-d '{"hello":"world"}'Define endpoints and sinks in config/hookpipe.yaml:
endpoints:
- id: github-push
path: /github/push
methods:
- POST
validation:
signature:
header: X-Hub-Signature-256
secret_env: GITHUB_WEBHOOK_SECRET
algorithm: hmac-sha256
sinks: # Fan-out to multiple sinks
- rabbitmq-main
message:
include_body: true
include_headers: true
header_filter:
- X-GitHub-Event
- X-GitHub-Delivery
sinks:
- id: rabbitmq-main
type: rabbitmq
settings:
url_env: RABBITMQ_URL
exchange: webhooks
routing_key: eventsSee Configuration for full reference.
Hookpipe watches the config file and reloads automatically when it changes. Validation rules, sink routing, message config, and allowed methods can be changed without restart. See Configuration for details.
| Sink | Type | Status |
|---|---|---|
| Stdout | stdout |
Available |
| RabbitMQ | rabbitmq |
Available |
| Kafka | kafka |
Available |
| HTTP Relay | http |
Available |
| SQS | sqs |
Available |
| Redis Streams | redis-stream |
Available |
| Google Pub/Sub | google-pubsub |
Available |
| SNS | sns |
Available |
| EventBridge | eventbridge |
Available |
See Sinks for details.
| Validator | Type | Use case |
|---|---|---|
| Bearer token | bearer |
Coolify, custom webhooks |
| HMAC-SHA256 | hmac-sha256 |
GitHub, Shopify |
| Stripe | stripe-v1 |
Stripe webhooks |
| API key | api-key |
Custom header + key |
| IP allowlist | ip-allowlist |
Restrict by IP/CIDR |
See Validators for details.
Every webhook is wrapped in a standardized envelope:
{
"id": "13979c7e-108c-48b1-aac5-ff9220a3875b",
"endpointId": "github-push",
"receivedAt": "2026-05-07T16:23:55.644839+00:00",
"method": "POST",
"path": "/github/push",
"remoteAddress": "192.30.252.1",
"headers": { "X-GitHub-Event": "push" },
"body": { "ref": "refs/heads/main" },
"metadata": {}
}See Message Envelope for full format.
| Variable | Description | Default |
|---|---|---|
HOOKPIPE_CONFIG_PATH |
Path to YAML config | config/hookpipe.yaml |
HOOKPIPE_MAX_BODY_SIZE_MB |
Max request body size (MB) | ~28.6 (Kestrel default) |
RABBITMQ_URL |
RabbitMQ connection string | — |
KAFKA_BROKERS |
Kafka broker list | — |
SEQ_URL |
Seq server URL | — (disabled) |
LOKI_URL |
Grafana Loki URL | — (disabled) |
See Configuration for all env vars and Logging for log destinations.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Liveness check |
GET |
/metrics |
Prometheus metrics |
* |
/* |
Dynamic — defined in config |
See Metrics for available metrics and Prometheus scrape config.
See CONTRIBUTING.md.