Tunnex
A self-hosted webhook inbox for teams, with tunnels. Point Stripe, GitHub or Telegram at one stable URL. Tunnex keeps every event, verifies its signature at the edge, and delivers a copy to every developer who is listening — including the ones who were offline when it arrived. Replay any event days later, and it still passes your signature check.
Website · Getting started · Inboxes · Self-hosting · Configuration · API · Changelog
30 seconds
pip install tunnex
tunnex login
tunnex inboxes create acme-stripe --provider stripe --secret whsec_... # → https://acme-stripe.tunnex.org
tunnex listen acme-stripe --forward 3000 # every developer runs this
Set https://acme-stripe.tunnex.org/webhooks/stripe as the endpoint in Stripe once. Every listener now gets
every event at localhost:3000/webhooks/stripe, with the original headers, so your handler verifies the
signature as usual.
Why
Providers give a team one webhook URL per environment (Stripe allows 16 endpoints, a Telegram bot exactly one, a GitHub App one), but the team has many developers. So people rewire the dashboard every time someone starts a tunnel, events that arrive while a laptop sleeps are lost, and replaying an old Stripe or Slack event fails its 5-minute signature window. The research and the comparison with Hookdeck, Convoy, Webhook Relay, smee.io and ngrok are in ADR 0001.
What you get
- Inboxes — a team-owned URL per provider that stores every request and acknowledges it immediately; size limits, retention, IP allowlists, custom acknowledgements.
- Fan-out and catch-up — every listener gets its own copy; a cursor per listener delivers what it missed; at-least-once delivery with retries while your app restarts; filters on path, headers and JSON fields.
- Signatures at the edge — Stripe, GitHub, Slack, Shopify, Standard Webhooks (Svix, Clerk, …) and Telegram; invalid events rejected by default; re-signing on replay for timestamped schemes.
- Teams — owner/admin/member roles, invite links, scoped and expiring API tokens (revocation disconnects live clients), an audit log.
- Runs where your code runs — official multi-arch images for the client and the server,
tunnex.yaml+ environment configuration, Docker Compose and Kubernetes sidecars, GitLab CI and GitHub Actions. - Tunnels — HTTPS and TCP to localhost with WebSockets and streaming, reserved subdomains, edge policies (basic auth, API keys, IP and path allowlists, email SSO, rate limits).
- A local inspector — every request and delivery on
127.0.0.1:4040, with replay. - For coding agents — an MCP server: start a listener, wait for the next webhook, read it, replay it.
Self-host
docker compose -f examples/self-hosted/docker-compose.yml up -d # server + PostgreSQL on *.lvh.me
tunnex login --server ws://connect.lvh.me:8081
Production (TLS, wildcard DNS, backups, upgrades, Kubernetes): docs/self-hosting.md.
Images: registry.gitlab.com/homycoder/tunnex/server and registry.gitlab.com/homycoder/tunnex/client.
Documentation
| Getting started | Install, tunnels, a team inbox, CI tokens, agents |
| Inboxes | Providers, listeners, filters, catch-up, replay and re-signing, roles |
| Configuration | Client environment and tunnex.yaml; every server setting |
| Self-hosting | Compose, Kubernetes, reverse proxy, backups, upgrades, scaling |
| API | Control-plane REST API, edge behaviour, local inspector API |
| Protocol | Wire format, negotiation, compatibility rules |
| Architecture | Request and webhook paths, layers, data |
| Security | Threat model, controls, review log |
| Benchmarks | Reproducible numbers |
| Decisions | Product focus, feature audit, single node, layering |
Development
uv venv .venv --python 3.12
uv pip install -e . -r tunnex_server/requirements.in --group dev
make check # ruff, mypy, the whole test suite with coverage
make run-server # a local server on http://connect.lvh.me:8081
Tests start real servers, clients and upstream apps in-process (no sleeps, no fixed ports). Set
TUNNEX_TEST_DATABASE_URL=postgresql+asyncpg://… to run them against PostgreSQL. See
CONTRIBUTING.md.
| Path | What |
|---|---|
tunnex/ |
Client: CLI, connection, inspector, local store, MCP server; protocol/ and domain/ are shared with the server |
tunnex_server/ |
Server: domain/ rules, services/, api/, edge/, transport/, db/ + migrations, web console |
examples/ |
Compose, Kubernetes, GitLab CI, GitHub Actions — tested in CI |
deploy/ |
How tunnex.org itself runs: Compose stack, Nginx, backups, monitoring, smoke test |
landing/ |
tunnex.org |
License
MIT. Security reports: SECURITY.md.
Metadata
Release files for tunnex 26.10.14.36
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tunnex-26.10.14.36.tar.gz | 149.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tunnex-26.10.14.36-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 318.7 kB
Release files / tunnex-26.10.14.36.tar.gz
| Download URL | tunnex-26.10.14.36.tar.gz |
|---|---|
| Size | 149.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
46bb39189d05e2f933e1baa9718c5621a073b66cad73e62812a85422bcee71cb
|
|
BLAKE2b-256 checksum How to use checksums |
a878d907d1789f65dba8265a06f5f59f61eb6f7560bcafcd84ece4bff0fc3b3e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / tunnex-26.10.14.36-py3-none-any.whl
| Download URL | tunnex-26.10.14.36-py3-none-any.whl |
|---|---|
| Size | 169.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
692fa94cb89521610e324bb8ac093e250cc79e549947c661637d50a407b95898
|
|
BLAKE2b-256 checksum How to use checksums |
6f435268abe5d7cfee78850fe0c3c15ad65fa9041bc9317db27298b53eaedc14
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|