cloudflare/pingora
Getting started
The canonical walkthrough is docs/quick_start.md in this repository — it builds a round-robin load balancer in about 60 lines. This page summarizes prerequisites and gives the quickest possible "hello, proxy" path.
Prerequisites
- Rust toolchain. Pingora's MSRV is 1.84 (declared in the workspace and the README). The MSRV rolls forward roughly every six months.
- Linux is tier-1. macOS and other Unixes mostly work for development. Windows support is "preliminary, best-effort." See
pingora-core/src/protocols/windows.rsfor the small Windows-only shims. - System libraries: Pingora needs build tooling for whichever TLS backend you pick.
opensslfeature: OpenSSL headers + Perl 5 (for the OpenSSL build scripts).boringsslfeature: Clang.rustls/s2nfeatures: pure-Rust or s2n-tls system library respectively.
- CPU: x86_64 and aarch64 are both supported.
Cloning and building
git clone https://github.com/cloudflare/pingora.git
cd pingora
cargo build
cargo test --workspaceThe workspace builds without TLS by default (no default features). For a more typical setup:
cargo build -p pingora --features "proxy lb cache openssl"There is also a Dockerfile at the repo root that produces a build environment with the right toolchain.
Running the load-balancer example
The complete code is at pingora-proxy/examples/load_balancer.rs. The minimum you need:
use async_trait::async_trait;
use pingora::prelude::*;
use std::sync::Arc;
pub struct LB(Arc<LoadBalancer<RoundRobin>>);
#[async_trait]
impl ProxyHttp for LB {
type CTX = ();
fn new_ctx(&self) {}
async fn upstream_peer(
&self,
_session: &mut Session,
_ctx: &mut (),
) -> Result<Box<HttpPeer>> {
let upstream = self.0.select(b"", 256).unwrap();
Ok(Box::new(HttpPeer::new(
upstream,
true,
"one.one.one.one".to_string(),
)))
}
}
fn main() {
let mut server = Server::new(None).unwrap();
server.bootstrap();
let upstreams = LoadBalancer::try_from_iter(["1.1.1.1:443", "1.0.0.1:443"]).unwrap();
let mut lb = http_proxy_service(&server.configuration, LB(Arc::new(upstreams)));
lb.add_tcp("0.0.0.0:6188");
server.add_service(lb);
server.run_forever();
}Server::new(None) skips CLI parsing. Pass Some(Opt::parse_args()) to wire up -c/--conf, -d/--daemon, -u/--upgrade, etc.
Test it:
curl 127.0.0.1:6188 -svo /dev/nullUseful CLI options
The full list comes from pingora-core/src/server/configuration/mod.rs (the Opt struct). The important ones:
| Flag | Effect |
|---|---|
-c PATH / --conf PATH |
Load YAML config |
-d / --daemon |
Detach and run in background |
-u / --upgrade |
Take over from a running instance (graceful upgrade) |
-t / --test |
Test the config file and exit |
Running the test suite
cargo test --workspace # unit tests for everything
cargo test --workspace --features "openssl proxy lb cache" # with TLS
cargo bench -p pingora-ketama # benchmarks (criterion-based)Pingora has integration tests under pingora-proxy/tests/ and pingora-core/tests/ that spin up real servers on loopback ports. Some tests are flaky in CI; see Debugging.
Using Pingora as a dependency
Add the umbrella crate plus the features you need:
[dependencies]
async-trait = "0.1"
pingora = { version = "0.8", features = ["lb", "proxy", "openssl"] }pingora's feature flags are the easiest entry point. They turn on the right pieces of pingora-core, pingora-proxy, pingora-cache, and pingora-load-balancing for you. See the cargo features documented inline in pingora/Cargo.toml.
Where to read next
- Architecture — the runtime topology
- Proxy phases — the full request lifecycle
- Configuration reference — every YAML key
- Patterns and conventions — error handling, async patterns, what
Result<()>means here
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.