torana
A reverse proxy in five megabytes

The smallest useful reverse proxy.

torana terminates TLS (HTTP/1.1 and HTTP/2), balances load, drains connections gracefully, and streams traffic to your upstreams, all from one static Rust binary with no runtime and no OpenSSL.

torana · तोरण : the ceremonial gateway arch. A small structure everything passes through.

MIT / Apache-2.0 Pure Rust, no OpenSSL 5.3 MB static binary
Weighted round robin at 60 / 30 / 10. Move your cursor to bend the flow, click for a burst.
5.3 MBdefault binary
5.5 MiBidle memory
4,571req/s · caddy 4,501
62tests, ~1s, no mocks
Measured, not marketed

Faster than servers ten times its size.

Same Docker network, same backend, same load generator. The harness ships in the repo. Run bench/bench.sh and get your own numbers in two minutes.

Throughput (req/s, higher is better)

torana
4,571
caddy
4,501
nginx
1,193

Idle memory (MiB, lower is better)

torana
5.5
caddy
21.9
nginx
9.7

HTTP/1.1 plain forwarding, 64 connections, 15 s, fortio inside one Docker network on a MacBook; nginx runs its stock config, and numbers drift a few percent between runs. Treat them as a relative comparison, then reproduce them with ./bench/bench.sh.

Honest by design

What it does, and what it doesn't, yet.

Every config field is either enforced or warns loudly at startup. No silent ignoring, no feature claims the code can't back.

Shipping today

  • ✓HTTP/1.1 and HTTP/2 (client-facing), fully streamed bodies, no buffering
  • ✓Host- and path-based routing across multiple routes, first match wins
  • ✓TLS termination with rustls; pure Rust, no OpenSSL
  • ✓Upstream keep-alive pooling, TCP_NODELAY on both legs
  • ✓Weighted round-robin load balancing
  • ✓Active health checks: unhealthy upstreams are skipped, not blackholed
  • ✓Retries on connect failure for GET/HEAD/OPTIONS with no body
  • ✓Sandboxed WASM plugins, opt-in: fuel-limited, no host access at all
  • ✓mTLS: mandatory client certs, verified fingerprint forwarded, never spoofable
  • ✓Automatic HTTPS via ACME, opt-in: RFC 8555, Let's Encrypt or a private CA
  • ✓Header rewriting and traffic mirroring on GET/HEAD/OPTIONS
  • ✓Zero-downtime reload on SIGHUP, validated before swap
  • ✓Graceful shutdown: in-flight requests finish before exit
  • ✓Prometheus /metrics, /healthz, structured JSON logs
  • ✓Embeddable: the engine is a separate crate usable inside your own server

On the roadmap

  • ✕HTTP/3
  • ✕HTTP/2 or TLS to upstreams (the proxy-to-upstream leg is always plain HTTP/1.1)
  • ✕Circuit breaking (retries and health checks exist; a faster-ejecting breaker doesn't yet)
  • ✕mTLS combined with ACME on the same listener
Where 5 MB wins

Built for the places big proxies don't fit.

Sidecar

Kubernetes sidecars

TLS termination and RED metrics next to your app container for 5.5 MiB of memory, not a service mesh's eighty. Probes wire straight into /healthz.

Edge

Routers, Pis, and edge boxes

A real reverse proxy on hardware where RAM is measured in megabytes and every binary ships over a slow link.

Cold start

Scale-to-zero platforms

Millisecond startup means the proxy is never the reason your function's cold start got slower.

Canary

Weighted rollouts

Send 5% of traffic to the new build with two lines of TOML and a SIGHUP, no orchestration required.

Compose

docker-compose front doors

One 5.5 MB scratch image routes your whole dev stack. Smaller than most base images' package index.

Public HTTPS

Internet-facing services

HTTP/2 and automatic ACME certificates on a binary a tenth the size of a full web server.

Metrics

Instrumenting legacy services

Put Prometheus request metrics in front of the service nobody dares recompile.

Zero trust

Internal service-to-service auth

mTLS makes client certificates mandatory and forwards a verified, unspoofable identity to your app.

CI

Integration test fixtures

Spin up a real proxy per test on a random port. torana's own suite runs 62 tests in about a second.

Appliance

Embedded products

Ship a proxy inside kiosks, appliances, and firmware images where every megabyte reaches a customer.

Install

Running in under a minute.

Build from source with stable Rust 1.75+, use the Docker recipe, or grab a prebuilt binary from releases. Full walkthroughs live in the docs.

from source
 git clone https://github.com/abhinavcdev/torana
cd torana && cargo build --release
./target/release/torana --config torana.toml 
docker
 docker build -t torana .
docker run -p 8080:8080 \
  -v $PWD/torana.toml:/etc/torana/torana.toml torana 
torana.toml · HTTP/2 + automatic HTTPS
 [[listener]]
addr = "0.0.0.0:443"
protocol = "https"

[listener.acme]            # h2 is automatic, nothing to set
domains = ["example.com"]
contact_emails = ["admin@example.com"]
cache_dir = "./acme-cache"

[[route]]
name = "default"
upstream = [{ addr = "http://127.0.0.1:3000" }] 
zero-downtime reload
 # edit torana.toml, then:
kill -HUP $(pgrep torana)
# invalid config? torana keeps the old one 

Next: the full configuration reference, Kubernetes and compose recipes, and troubleshooting.