cloudflare/pingora
Deployment
Pingora is a binary you run, not a service mesh you install. Deployment patterns:
Single-host deployment
The simplest case: a Pingora binary, a YAML config, and a systemd unit. The user guide page docs/user_guide/systemd.md is the canonical recipe.
The systemd unit pattern:
[Service]
ExecStart=/usr/local/bin/pingora -c /etc/pingora/conf.yaml
ExecReload=/bin/kill -SIGQUIT $MAINPID
KillSignal=SIGTERM
Restart=on-failureExecReload sends SIGQUIT to trigger a graceful upgrade. Combined with daemon_wait_for_ready: true, systemd waits for the new instance to come up before tearing down the old one.
Process model
graph TD
pid[Main process]
sup[Supervisor task<br/>signal handling]
rt1[Runtime A<br/>service 1]
rt2[Runtime B<br/>service 2]
rtbg[Runtime C<br/>background services]
pool[OS-level blocking pool<br/>(spawn_blocking)]
pid --> sup
pid --> rt1
pid --> rt2
pid --> rtbg
rt1 -.-> pool
rt2 -.-> poolOne process per Pingora instance. Inside the process, one tokio runtime per service. Blocking work goes through tokio's blocking thread pool (size configurable as of 0.7.0).
YAML configuration
A minimal production config:
---
version: 1
threads: 8
pid_file: /run/pingora.pid
error_log: /var/log/pingora/error.log
upgrade_sock: /run/pingora-upgrade.sock
user: pingora
group: pingora
work_stealing: true
upstream_keepalive_pool_size: 1024
daemon_wait_for_ready: true
daemon_ready_timeout_seconds: 60Every key is documented at Configuration.
Graceful upgrade in production
The defining operational characteristic is zero-downtime binary swaps. Trigger:
systemctl reload pingora
# or directly:
kill -SIGQUIT $(cat /run/pingora.pid) && /usr/local/bin/pingora -c /etc/pingora/conf.yaml -d -uSee Graceful upgrade for the full state machine.
Container deployment
The Dockerfile at the repo root is a build-environment image, not a deployment image. To ship Pingora in a container, build it once, copy the binary into a runtime image, and run it.
FROM rust:1.84 AS build
COPY . /pingora
WORKDIR /pingora
RUN cargo build --release -p pingora --features "proxy lb cache openssl"
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y libssl3 ca-certificates
COPY --from=build /pingora/target/release/your-binary /usr/local/bin/
COPY conf.yaml /etc/pingora/conf.yaml
EXPOSE 80 443
CMD ["/usr/local/bin/your-binary", "-c", "/etc/pingora/conf.yaml"]Graceful upgrade across container restarts is awkward — the upgrade socket would need to survive a container teardown. In practice, container deployments restart pods/containers and rely on the load balancer in front to drain.
Linux specifics
- Tier 1 platform per README. Most testing happens on Linux.
- Listen FD inheritance uses
SO_REUSEPORTandSCM_RIGHTS. Both are Linux-only paths inpingora-core. daemonizecrate for double-fork detachment.- systemd integration via
daemon_wait_for_readyandSIGUSR1.
macOS and other Unixes mostly work for development. Windows is preliminary.
Sizing
There's no published guidance for "how many threads should I run." Cloudflare's production binary is heavily tuned. A reasonable starting point:
threads: 2 * num_cpusfor work-stealingthreads: num_cpusfor non-work-stealing
The tokio.blocking_threads config (0.7.0) caps the spawn-blocking pool — important if your ProxyHttp impl does CPU-blocking work.
Hot-reloading config
Pingora doesn't support hot config reload. To change the YAML, restart (typically via graceful upgrade). The -t/--test CLI flag tests a config file's syntax without starting the server, so you can validate before restart.
Health endpoints
Pingora doesn't expose a /health endpoint by default. You can build one as a synthetic response in request_filter (docs/user_guide/modify_filter.md) or as a separate listener service.
See also
- Configuration reference
- Graceful upgrade
docs/user_guide/systemd.mddocs/user_guide/start_stop.md
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.