Metadata-Version: 2.5
Name: tunnex
Version: 26.10.14.34
Summary: Self-hosted webhook inbox for teams, with HTTP and TCP tunnels to localhost
Project-URL: Homepage, https://tunnex.org
Project-URL: Documentation, https://gitlab.com/homycoder/tunnex/-/tree/main/docs
Project-URL: Source, https://gitlab.com/homycoder/tunnex
Project-URL: Changelog, https://gitlab.com/homycoder/tunnex/-/blob/main/CHANGELOG.md
Project-URL: Issues, https://gitlab.com/homycoder/tunnex/-/issues
Author-email: Tunnex <dev@tunnex.org>
License-Expression: MIT
License-File: LICENSE
Keywords: github,localhost,mcp,ngrok,self-hosted,stripe,tunnel,webhooks
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: Proxy Servers
Classifier: Topic :: Software Development :: Testing
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: aiosqlite>=0.19
Requires-Dist: click<9,>=8.1
Requires-Dist: fastapi>=0.115
Requires-Dist: httpx<1,>=0.27
Requires-Dist: mcp<3,>=2.0
Requires-Dist: pydantic<3,>=2.6
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Requires-Dist: sniffio>=1.3
Requires-Dist: sqlalchemy[asyncio]<2.1,>=2.0.30
Requires-Dist: uvicorn>=0.30
Requires-Dist: uvloop>=0.19; sys_platform != 'win32'
Requires-Dist: websockets<17,>=15.0
Description-Content-Type: text/markdown

# 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.

[![pipeline](https://gitlab.com/homycoder/tunnex/badges/main/pipeline.svg)](https://gitlab.com/homycoder/tunnex/-/pipelines)
[![coverage](https://gitlab.com/homycoder/tunnex/badges/main/coverage.svg)](https://gitlab.com/homycoder/tunnex/-/pipelines)
[![PyPI](https://img.shields.io/pypi/v/tunnex)](https://pypi.org/project/tunnex/)
[![Python](https://img.shields.io/pypi/pyversions/tunnex)](https://pypi.org/project/tunnex/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)

[Website](https://tunnex.org) · [Getting started](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/getting-started.md) · [Inboxes](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/inboxes.md) ·
[Self-hosting](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/self-hosting.md) · [Configuration](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/configuration.md) · [API](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/api.md) ·
[Changelog](https://gitlab.com/homycoder/tunnex/-/blob/main/CHANGELOG.md)

## 30 seconds

```bash
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.

![An inbox in the console: events with signature status and per-listener deliveries](https://gitlab.com/homycoder/tunnex/-/raw/main/docs/assets/console-inbox.png)

## 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](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/adr/0001-product-focus.md).

## 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](https://gitlab.com/homycoder/tunnex/-/tree/main/examples).
- **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.

![The local inspector showing an inbox delivery](https://gitlab.com/homycoder/tunnex/-/raw/main/docs/assets/inspector.png)

## Self-host

```bash
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](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/self-hosting.md).
Images: `registry.gitlab.com/homycoder/tunnex/server` and `registry.gitlab.com/homycoder/tunnex/client`.

## Documentation

| | |
|---|---|
| [Getting started](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/getting-started.md) | Install, tunnels, a team inbox, CI tokens, agents |
| [Inboxes](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/inboxes.md) | Providers, listeners, filters, catch-up, replay and re-signing, roles |
| [Configuration](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/configuration.md) | Client environment and `tunnex.yaml`; every server setting |
| [Self-hosting](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/self-hosting.md) | Compose, Kubernetes, reverse proxy, backups, upgrades, scaling |
| [API](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/api.md) | Control-plane REST API, edge behaviour, local inspector API |
| [Protocol](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/protocol.md) | Wire format, negotiation, compatibility rules |
| [Architecture](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/architecture.md) | Request and webhook paths, layers, data |
| [Security](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/security.md) | Threat model, controls, review log |
| [Benchmarks](https://gitlab.com/homycoder/tunnex/-/blob/main/docs/benchmarks.md) | Reproducible numbers |
| [Decisions](https://gitlab.com/homycoder/tunnex/-/tree/main/docs/adr) | Product focus, feature audit, single node, layering |

## Development

```bash
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](https://gitlab.com/homycoder/tunnex/-/blob/main/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](https://gitlab.com/homycoder/tunnex/-/blob/main/LICENSE). Security reports: [SECURITY.md](https://gitlab.com/homycoder/tunnex/-/blob/main/SECURITY.md).
