Overview
The problem
Real edge proxies do mTLS termination, JWT validation in-line,
per-route rate limiting, and cert hot-reload — and they make
defensible decisions on body buffering, HTTP/2 stream control, and
connection pooling. ferryman-edge is the project that gets the
Cloudflare Pingora team to reply.
Architecture (delta on top of P2)
Client (with mTLS cert)
|
v
+--------+---------+
| rustls TLS+mTLS | cert reload via SIGUSR1
| + JWT validate | (no connection drops)
+--------+---------+
|
v
+--------+---------+
| per-tenant rate | governor crate, keyed by JWT.sub
| limit (per route)|
+--------+---------+
|
v
+--------+---------+
| RouteService |
| (P2's table) |
+--------+---------+
|
v
+--------+---------+
| hyper client | pool: 1 conn per upstream * N
| HTTP/2 multiplex | feature flag: boxed_body vs collected
+--------+---------+
|
v
upstream svc
Stack
| Layer | Crate / Tool |
|---|---|
| Async runtime | tokio 1.47 (full) |
| HTTP server | hyper 1.5 + hyper-util + tower-http |
| TLS / mTLS | rustls 0.23 (aws-lc-rs provider) + tokio-rustls 0.26 + rustls-pemfile 2 + rustls-pki-types |
| AuthN | jsonwebtoken 9 + moka 0.12 (future cache, 10k × 5min) |
| Rate limit | governor 0.7 (keyed GCRA) |
| Config / hot-swap | serde + toml 0.8 + arc-swap; reload via SIGUSR1 |
| Observability | tracing + metrics-exporter-prometheus 0.16 |
| CLI | clap 4 |
| Container build | cargo-chef multi-stage; distroless final (NOT scratch — aws-lc-rs needs libc) |
| Deploy | Fly.io 2-region (sin + iad) |
| CI | GHA (stable + beta) + cargo-deny + cargo-nextest + criterion (non-blocking) + mTLS smoke |
Pinned versions live in Cargo.toml.