A tiny, self-hosted receiver for Dozzle's Alerts & Webhooks. Point Dozzle's Log, Metric and Event alerts at hook2catch and get a searchable, multi-organization dashboard.
The problem
Dozzle is a great real-time Docker log viewer, but it doesn't keep history or give you a place to review errors later. hook2catch is a minimal receiver for its three alert types: it stores what Dozzle sends, keeps it for a configurable number of days, and shows it in a small web dashboard — nothing more, nothing less.
Fires when a container's output matches a rule you set in Dozzle.
Fires when a container's resource usage passes a limit you define.
Fires on state changes Docker itself reports for a container.
What you get
Every part of hook2catch exists to make incoming webhook traffic easier to search and understand — not to become a platform.
Every event stays correctly tagged per source, even if container names collide across them.
Pick a source to see its containers with event counts, click one to filter to just its events.
Last hour to all time, or a custom window. Click a chart spike to zoom in, step back out with one button.
Events over time, stacked by level, drawn inline with no charting library. Hover any slice for its breakdown.
Refreshes every 10s without collapsing expanded rows or losing your scroll position. Page back through older events anytime.
Pin the one line you'll need to reference later — starring survives retention cleanup.
Build a source/type/level/search combination, name it, and reapply it later with one click.
File-based users with bcrypt hashes and login throttling — or turn it off behind your own auth layer.
7 days by default, or set it to keep everything forever. Starred events are never swept.
SQLite (WAL mode) for storage, a single Docker image with a built-in health check.
Switchable anytime, remembered per browser.
Create a source, rotate its token, or delete it (with its events) without touching the server.
Architecture
One Python service, one SQLite file. No queue, no agent watching your Docker socket, nothing else to operate.
Log, Metric or Event — each posted as JSON to POST /webhook/<source-slug> with a per-source bearer token.
Tagged by source in SQLite (WAL mode), kept for RETENTION_DAYS — 0 to keep forever.
Filter by source, container, type, level, time and text. See volume, severity and the noisiest containers at a glance.
Quick start
One Docker command once your secret key and first user are set up.
# 1. clone and configure git clone https://github.com/erogluefe/hook2catch.git cd hook2catch cp .env.example .env cp data/users.yml.example data/users.yml # 2. generate a real SECRET_KEY into .env python3 -c "import secrets; print(secrets.token_urlsafe(32))" # 3. create a login user .venv/bin/python scripts/generate_password.py # 4. start it docker compose up -d ✓ hook2catch running at http://localhost:8000
AUTH_ENABLED=true and no real SECRET_KEY — no forgeable default cookies./webhook/<slug>.Before you expose it
hook2catch is intentionally small, but it doesn't cut corners on the basics.
No forgeable sessions. Startup fails without a real SECRET_KEY when auth is enabled.
No source enumeration. An unknown slug and a wrong token return the same response, compared in constant time.
No silent registration. The webhook endpoint can never create a source — only an authenticated session can.
Throttled logins. Repeated failures from one IP are locked out for a configurable window.
No markup injection. Payload fields are always rendered as text, never parsed as HTML.
Bounded requests. Body size and field lengths are capped so one oversized alert can't exhaust memory.
MIT licensed and intentionally small. Issues and PRs are welcome — a few directions being explored next:
Self-hosted, open source, one Docker command away.