Self-hosted webhook relay — receive events, match rules, and dispatch notifications.
2.6K
Webhooks in. Notifications out.
HookRel is a self-hosted webhook relay. It receives webhook events from your applications, matches them against your rules, formats them using templates, and dispatches notifications to your chosen providers — all without writing a single line of code.
Your App → HookRel → Rules → Message Template → Provider
services:
hookrel:
image: baz1536/hookrel:latest
container_name: hookrel
restart: unless-stopped
ports:
- "3551:3551"
environment:
PORT: 3551
NODE_ENV: production
PUBLIC_URL: http://your-server-ip:3551
DB_TYPE: sqlite
DB_PATH: /app/data/hookrel.db
AUTH_ENABLED: "true"
ENCRYPTION_KEY: "replace_with_64_hex_chars"
SESSION_SECRET: "replace_with_64_hex_chars"
volumes:
- hookrel_data:/app/data
- hookrel_logs:/app/logs
volumes:
hookrel_data:
hookrel_logs:
Then open http://your-server-ip:3551 — you'll be prompted to create an admin account on first launch.
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Run twice — once for ENCRYPTION_KEY, once for SESSION_SECRET.
| Variable | Default | Description |
|---|---|---|
PORT | 3551 | Port the server listens on |
NODE_ENV | production | Node environment |
PUBLIC_URL | (none) | Public-facing base URL — used to build webhook URLs shown in the UI |
DB_TYPE | sqlite | Database backend — sqlite or mongodb |
DB_PATH | ./data/hookrel.db | SQLite file path, or full MongoDB connection URI |
AUTH_ENABLED | true | Set to false to bypass login (trusted network only) |
ENCRYPTION_KEY | (required) | 64-char hex string — encrypts provider credentials at rest |
SESSION_SECRET | (required) | 64-char hex string — signs session cookies |
LOG_LEVEL | info | Log verbosity — error, warn, info, debug |
LOG_DIR | ./logs | Directory for daily rotating log files |
TZ | (system) | Timezone (e.g. Europe/London) |
HTTPS_PROXY | (none) | Proxy for outbound HTTPS (Telegram, Pushover, MS Graph, email) |
HTTP_PROXY | (none) | Proxy for outbound HTTP |
NO_PROXY | (none) | Comma-separated hosts/CIDRs to bypass the proxy |
Important:
ENCRYPTION_KEYandSESSION_SECRETshould be long, random strings. Generate with:openssl rand -hex 32If
ENCRYPTION_KEYchanges, existing provider credentials will no longer decrypt and must be re-entered.
| Path | Description |
|---|---|
/app/data | Database and configuration — mount this to persist your data |
/app/logs | Daily rotating log files |
| Provider | Format |
|---|---|
| SMTP | HTML or plain text |
| Microsoft 365 | HTML or plain text (via Microsoft Graph API) |
| Microsoft Teams | Plain text |
| Telegram | Plain text |
| Pushover | Plain text |
| Slack | Plain text |
| Discord | Plain text |
| Gotify | Plain text |
| ntfy | Plain text |
| Source | Known events |
|---|---|
| Sonarr | Grab, Download, Rename, SeriesAdd, Health, and more |
| Radarr | Grab, Download, Rename, MovieAdded, Health, and more |
| Plex | media.play, media.pause, media.stop, library.new, and more |
| Jellyfin | ItemAdded, PlaybackStart, PlaybackStop, UserCreated, and more |
| Prowlarr | Health, ApplicationUpdate |
| Seerr / Overseerr | Media pending/approved/available, issue events |
| Tautulli | play, stop, pause, resume, watched, recently_added |
| Uptime Kuma | Monitor down / up |
| Custom | Any app — tokens learned automatically from live payloads |
services:
hookrel:
image: baz1536/hookrel:latest
container_name: hookrel
restart: unless-stopped
ports:
- "3551:3551"
environment:
PORT: 3551
NODE_ENV: production
PUBLIC_URL: http://your-server-ip:3551
DB_TYPE: mongodb
DB_PATH: mongodb://hookrel:yourpassword@mongodb:27017/hookrel?authSource=admin
AUTH_ENABLED: "true"
ENCRYPTION_KEY: "replace_with_64_hex_chars"
SESSION_SECRET: "replace_with_64_hex_chars"
volumes:
- hookrel_logs:/app/logs
mongodb:
image: mongo:8.2.7
container_name: mongodb
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: hookrel
MONGO_INITDB_ROOT_PASSWORD: yourpassword
volumes:
- mongodb_data:/data/db
volumes:
hookrel_logs:
mongodb_data:
Each source gets a unique URL and bearer token. Configure your application to POST to:
POST https://your-hookrel-url/webhook/<slug>
With either:
Authorization: Bearer <token>
or:
X-API-Key: <token>
Note: Plex webhooks are sent as
multipart/form-data(Plex Pass required). HookRel handles this automatically.
Set PUBLIC_URL to your external domain so webhook URLs in the UI are correct:
PUBLIC_URL=https://hookrel.example.com
https://github.com/baz1536/hookrel
MIT — Copyright © 2026 dBR Promotions
Content type
Image
Digest
sha256:6b89df5b6…
Size
93.2 MB
Last updated
15 days ago
docker pull baz1536/hookrel