CLAUDE.md · joaoh82/rustunnel
CLAUDE.md from joaoh82/rustunnel: 251 lines covering What is rustunnel, Parent project, Common Commands, Workspace Structure and more.
Template by joaoh82
Chalk Labs
Need help deploying CLAUDE.md · joaoh82/rustunnel?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
Install
Works with Claude Code. Read the repository before you give any tool access to your data.
curl -fsSL https://raw.githubusercontent.com/joaoh82/rustunnel/main/CLAUDE.md -o CLAUDE.md
Read it and adapt it to your project before use.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: code-generation
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
What's in it
A CLAUDE.md file: project memory Claude Code loads at the start of every session.
- For
- Claude Code
- Length
- 251 lines
- File
CLAUDE.md
Sections
- What is rustunnel
- Parent project
- Common Commands
- Workspace Structure
- Architecture
- Databases
- Configuration
- Observability
- Repository Conventions
- CI
- Knowledge Base
First lines (shown under the repo's AGPL-3.0 license)
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What is rustunnel
rustunnel is a self-hosted secure tunnel server written in Rust (similar to ngrok). It exposes local services through a public server via encrypted WebSocket connections with TLS termination, HTTP/TCP/UDP proxying, P2P direct mode (NAT hole punching via STUN/QUIC), a live dashboard, Prometheus metrics, and audit logging.
## Parent project
**Parent project:** [rustunnel](/Users/joaoh82/projects/rustunnel/CLAUDE.md) — read for shared dev commands, env vars, cross-service architecture, **and the global working guidelines** (never-touch-main, task management, pull-request registration, reserved ports, engineering defaults). Those guideline sections live only in the parent `CLAUDE.md` — this file does not duplicate them.
### How I fit in
This crate (`rustunnel/`) is the **core tunnel server + CLI client + MCP server**. Siblings in the parent meta-repo:
| Sibling | Stack | Dev port | Role |
|---------|-------|----------|------|
| `rustunnel-web/` | Rust (Axum) + Next.js 15 | 3001 / 3000 | Platform API + public website + marketing pages (registration, JWT, billing) |
| `rustunnel-admin-dashboard/` | Next.js 14 | 3002 | Internal admin UI |
| `rustunnel-private/` | Markdown / Bash / Ansible | — | Ops docs, provisioning playbooks |
| `docs/` | Mintlify (MDX) | 3000 | Public documentation |
| `homebrew-rustunnelcli/` | Ruby | — | Homebrew tap formula |
| `rustunnel-status/` | Upptime (YAML + Actions) | — | `status.rustunnel.com`, probes every edge |
This server shares its **PostgreSQL database** with `rustunnel-web/platform-api` (the `tokens` table is the auth boundary). Edge servers (`eu`, `us`, `ap`) all run this binary; `platform-api` runs on a separate VPS at `api.rustunnel.com`.
## Common Commands
```bash
# Build
cargo build --workspace
make build
make build-full # rebuild dashboard UI (Next.js export) + server crate (use after UI changes)
# Release build (optimized binaries: rustunnel-server, rustunnel-client, rustunnel-mcp)
make release
# Test (requires PostgreSQL — start first)
make db-start
make test
# Or manually:
TEST_DATABASE_URL=postgres://rustunnel:test@localhost:5432/rustunnel_test cargo test --workspace
# Stop test DB
make db-stop
# Lint & format
make fmt # cargo fmt --all
make lint # cargo clippy --workspace --all-targets -- -D warnings
make check # fmt check + clippy (mirrors CI)
# Run a single test
TEST_DATABASE_URL=postgres://rustunnel:test@localhost:5432/rustunnel_test cargo test <test_name> -p <crate_name>
# Install pre-push hooks (run once)
make install-hooks
```
### Local Development
```bash
# One-time TLS cert in /tmp/rustunnel-dev (re-run after reboot — tmpfs is wiped)
make dev-setup
# Run server (uses deploy/local/server.toml: self-signed cert, require_auth = false)
cargo run -p rustunnel-server -- --config deploy/local/server.toml
# Run client — HTTP, TCP, UDP
cargo run -p rustunnel-client -- http 3000 --server localhost:4040 --token dev-secret-change-me --insecure
cargo run -p rustunnel-client -- tcp 5432 --server localhost:4040 --token dev-secret-change-me --insecure
cargo run -p rustunnel-client -- udp 27015 --server localhost:4040 --token dev-secret-change-me --insecure
# Dashboard UI (Next.js, dev mode — proxies API to localhost:8443)
make ui-install # first time
make ui-dev
```
## Workspace Structure
Four crates in `crates/`, plus integration tests and a Next.js dashboard (`dashboard-ui/`) whose static export is embedded into the server binary:
| Crate | Purpose |
|-------|---------|
| `rustunnel-protocol` | Shared `ControlFrame` enum + `TunnelProtocol` (Http/Https/Tcp/Udp/P2p) and serialization |
| `rustunnel-server` | Server: control plane, HTTP/TCP/UDP edges, dashboard, TLS, ACME |
| `rustunnel-client` | CLI client with auto-reconnect, local port forwarding, P2P/STUN, region auto-select, Ratatui terminal UI (`src/tui/`) and a loopback request inspector (`src/inspect/`) |
| `rustunnel-mcp` | MCP server exposing rustunnel as tools to AI agents |
## Architecture
### High-Level Data Flow
```
Internet → HTTP/TCP/UDP Edge → TunnelCore (router) → Control Plane → yamux stream → Local service
↘ P2P direct (QUIC, NAT-punched) ↗
```
The server spawns concurrent tasks for each subsystem:
- **Control Plane** (`:4040`) — WebSocket server for client connections; handles auth, tunnel registration, `NewConnection` delivery, P2P signaling
- **HTTP/HTTPS Edge** (`:80` / `:443`) — TLS-terminated reverse proxy; routes by subdomain
- **TCP Edge** (`:20000+`) — Raw TCP proxy; routes by assigned port
- **UDP Edge** (configurable port range) — UDP proxy; routes by assigned port
- **Dashboard** (`:8443`) — REST API + embedded Next.js SPA + per-instance SQLite request capture
- **Prometheus Metrics** (`:9090`)
- **ACME Renewal** (background, optional — Let's Encrypt + Cloudflare DNS-01)
### Connection Handoff (Core Mechanism)
1. HTTP/TCP/UDP edge receives inbound connection → registers a `pending_conn` (oneshot channel) in `TunnelCore` with a `conn_id`
2. Control plane sends `NewConnection { conn_id, protocol }` to the relevant client over WebSocket
3. Client opens a new yamux stream for that `conn_id`
4. Server resolves the oneshot, unblocking the edge task
5. Edge task and client stream data bidirectionally through yamux
### P2P Direct Mode
For peer-to-peer tunnels (`TunnelProtocol::P2p`), the server acts as a rendezvous/signaling broker only — bytes do not flow through it once the punch succeeds:
1. Publisher registers a named tunnel with a `secret_hash`; reports its NAT type and STUN-mapped addresses (`P2pNatInfo`)
2. Subscriber sends `P2pConnect { target_tunnel_name, secret_hash }`
3. Server uses `classify_nat_pair` to pick a hole-punching strategy and exchanges peer addresses via P2P frames
4. Both peers establish a direct **QUIC** connection (via `quinn`) — server is out of the data path
5. Falls back to relayed mode when NAT classification rules out direct connectivity
Client implementation: `crates/rustunnel-client/src/p2p_direct.rs`, `stun.rs`. Server-side state: `P2pPublisher` in `core/router.rs`.
### TunnelCore (`crates/rustunnel-server/src/core/router.rs`)
Central shared state, `Arc`-wrapped and passed to all subsystems:
```rust
pub struct TunnelCore {
http_routes: DashMap<String, Arc<TunnelGroup>>, // subdomain → group of members
tcp_routes: DashMap<u16, Arc<TunnelGroup>>, // port → group of members
udp_routes: DashMap<u16, Arc<TunnelGroup>>, // port → group of members
p2p_tunnels: DashMap<String, P2pPublisher>, // name → P2P publisher
sessions: DashMap<Uuid, SessionInfo>, // connected clients
available_tcp_ports: Mutex<Vec<u16>>, // free TCP port pool
available_udp_ports: Mutex<Vec<u16>>, // free UDP port pool
tunnel_index: DashMap<Uuid, TunnelKey>, // tunnel_id → key (O(1) removal)
pending_conns: DashMap<Uuid, oneshot::Sender>, // conn_id → yamux resolver
tcp_events: broadcast::Sender<TcpTunnelEvent>,
udp_events: broadcast::Sender<UdpTunnelEvent>,
rate_limiter: Arc<RateLimiter>, // per-tunnel token bucket
ip_limiter: Arc<IpRateLimiter>, // per-source-IP sliding window
}
```
Each route key resolves to a `TunnelGroup` of one or more `GroupMember`s
(see `core/tunnel.rs`). Today every group has exactly one member — the route
shape is in place ahead of TUNNEL-7 group-based load balancing (`see
../rustunnel-private/docs/development/load-balancing-and-health-checks.md`).
`resolve_http` / `resolve_tcp` / `resolve_udp` pick a healthy member uniformly
at random; ungrouped registrations stay healthy for life. The
`[load_balancing] enabled` flag in `server.toml` is the kill switch for
honouring multi-member groups (defaults to `false`; flipped on per region
during the EU → US → AP rollout).
### Protocol (`crates/rustunnel-protocol/src/frame.rs`)Signals
- Stars
- 657
- Forks
- 48
- Open issues
- 0
- Contributors
- 4
- Last commit (this folder)
- Jul 31, 2026 (3 months ago)
- Last release
- Sep 3, 2026 (1 month ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- AGPL-3.0
- Repository
- github.com/joaoh82/rustunnel
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from joaoh82
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get CLAUDE.md · joaoh82/rustunnel running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
CLAUDE.md · joaoh82/rustunnel. Agent Mart. https://agentmart.dev/templates/joaoh82-rustunnel-claude-md (last updated 2026-10-24)