
A reverse proxy like nginx, built on pingora, simple and efficient.
Before the pingap version is stable, no pull requests will be accepted. If you have any questions, please create a new issue first.

Pingap is a high-performance reverse proxy powered by the Cloudflare Pingora . It simplifies operational management by enabling dynamic, zero-downtime configuration hot-reloading through concise TOML files and an intuitive web admin interface.
Its core strength lies in a powerful plugin system, offering over twenty out-of-the-box features for Authentication (JWT, Key Auth), Security (CSRF, IP/Referer/UA Restrictions), Traffic Control (Rate Limiting, Caching), Content Modification (Redirects, Content Substitution), and Observability (Request ID). This makes Pingap not just a proxy, but a flexible and extensible application gateway, engineered to effortlessly handle complex scenarios from API protection to modern web application deployments.
中文说明 | Documentation · 中文文档 | Examples | Plugins | Crates
flowchart LR
internet("Internet") -- request --> pingap["Pingap"]
pingap -- proxy:pingap.io/api/* --> apiUpstream["10.1.1.1,10.1.1.2"]
pingap -- proxy:cdn.pingap.io --> cdnUpstream["10.1.2.1,10.1.2.2"]
pingap -- proxy:/* --> upstream["10.1.3.1,10.1.3.2"]
🚀 High Performance & Reliability
🔧 Dynamic & Easy to Use
🧩 Powerful Extensibility
📊 Modern Observability
{:ja4} in access logs, $ja4 in upstream headers) to tell clients apart by their TLS stack, on OpenSSL and rustls builds alike.The easiest way to get started with Pingap is by using Docker Compose.
docker-compose.yml file:# docker-compose.yml
version: '3.8'
services:
pingap:
image: vicanso/pingap:latest # For production, use a specific version like vicanso/pingap:0.12.1-full
container_name: pingap-instance
restart: always
ports:
- "80:80"
- "443:443"
volumes:
# Mount a local directory to persist all configurations and data
- ./pingap_data:/opt/pingap
environment:
# Configure using environment variables
- PINGAP_CONF=/opt/pingap/conf
- PINGAP_ADMIN_ADDR=0.0.0.0:80/pingap
- PINGAP_ADMIN_USER=pingap
- PINGAP_ADMIN_PASSWORD=<YourSecurePassword> # Change this!
command:
# Start pingap and enable hot-reloading
- pingap
- --autoreload
mkdir pingap_data
docker-compose up -d
Your Pingap instance is now running! You can access the web admin interface at http://localhost/pingap with the credentials you set.
For Linux and macOS, you can install the latest pre-built binary to /usr/local/bin/pingap with one command:
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | sh
Optional environment variables:
PINGAP_FULL=1 — install the -full build (all optional features enabled)PINGAP_LIBC=gnu — on Linux, use the glibc build instead of the default musl static buildPINGAP_TLS=rustls — on Linux, install the -rustls-full build (rustls TLS backend, all optional features, no OpenSSL); see TLS backend# Full-featured build
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | PINGAP_FULL=1 sh
Supported targets: Linux x86_64/arm64, Darwin x86_64/arm64. See the releases page for all available assets.
For more detailed instructions, including running from a binary, check out our Documentation.
A single command is enough to serve a domain over https and forward it to a backend:
# certificate requested from let's encrypt
pingap --domain=pingap.io --upstream=192.168.1.1:3000
# or bring your own certificate
pingap --domain=pingap.io --upstream=192.168.1.1:3000 --cert=/etc/ssl/pingap.io
Without --cert, Pingap asks Let's Encrypt for a certificate through the
HTTP-01 challenge, so pingap.io must resolve to this host and port 80 must be
reachable from the internet. The issued certificate is kept in
~/.pingap/acme/<domains>.toml and reused on restart — issuing is rate limited,
so do not delete it. Everything else still comes from the command line: changing
--upstream takes effect on the next start without touching the certificate.
--cert accepts the certificate itself or the directory holding it — the common
fullchain.pem / privkey.pem, cert.pem / key.pem and tls.crt / tls.key
layouts are detected automatically, use --key for anything else. The listener
defaults to 0.0.0.0:443 when there is a certificate and 0.0.0.0:80 when there
is neither a certificate nor a domain, and --addr overrides it. --upstream
takes a comma separated list of backends, --domain a comma separated list of
hosts (omit it to serve every host over plain http). Requests for a host that
is not listed are answered with 404.
The configuration is generated on every start, so it cannot be edited through
the admin UI: for anything beyond a single server use --conf, which cannot be
combined with these flags.
Pingap is designed to adapt to configuration changes without downtime.
Hot Reload (--autoreload): For most changes—like updating upstreams, locations, or plugins—Pingap applies the new configuration within 10 seconds without a restart. This is the recommended mode for containerized environments.
Graceful Restart (-a or --autorestart): For fundamental changes (like modifying server listen ports), this mode performs a full, zero-downtime restart, ensuring no requests are dropped.
The hand-over is readiness-driven rather than timed: the replacement is started with -d -u, reports back over a unix socket next to the upgrade socket the moment it is ready to take over the listeners, and only then does the running process send itself SIGQUIT. If the replacement exits, its daemon dies, or basic.restart_ready_timeout (default 1m) passes first, the restart is abandoned and the running process keeps serving.
make dev
If you need a web admin, you should install nodejs and build web asssets.
# generate admin web asset
cd web
npm i
cd ..
make build-web