
A reverse proxy like nginx, built on pingora, simple and efficient.
A reverse proxy and application gateway built on Cloudflare Pingora. It is configured through TOML files or a web admin that is part of the binary, takes changes without a restart, and comes with more than thirty plugins.
δΈζθ―΄ζ | Documentation Β· δΈζζζ‘£ | Examples | Plugins | Crates | Upgrading
pingap -t checks it before it is stored, earlier versions can be kept and restored, and there are read-only accounts and API tokens. Its home page charts the traffic of the last fifteen minutes - rate, status, latency, each upstream - without Prometheus.--autoreload). What needs new listeners is applied by a restart that hands the sockets over (--autorestart, for a daemon on Linux), and the running process keeps serving if its replacement does not come up.-t builds everything a start would, --strict refuses keys it does not know, --diff shows what a change would do. TOML, HCL or KDL, in files or in etcd, with secrets taken from the environment or from files.The rest of what a reverse proxy does is there too: HTTP/1.1, HTTP/2, WebSocket and gRPC-web; routing by host, path and regular expression; round robin, least connections, consistent hashing and sticky sessions, with health checks, retries and a circuit breaker; backends from DNS (A/AAAA, SRV) or Docker labels; the PROXY protocol on listeners and towards upstreams; OpenSSL or rustls.
Metrics, tracing and image optimisation are in the -full builds.
# docker-compose.yml
services:
pingap:
image: vicanso/pingap:latest # for production, pin a release: vicanso/pingap:<version>-full
container_name: pingap-instance
restart: always
ports:
- "80:80"
- "443:443"
volumes:
# everything Pingap keeps: configuration, certificates, cache
- ./pingap_data:/opt/pingap
environment:
- 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:
- pingap
- --autoreload
mkdir pingap_data
docker compose up -d
The admin is at http://localhost/pingap. Images are tagged latest, full and rustls-full, and <version>, <version>-full, <version>-rustls-full for a release. Each also has a -distroless twin without a shell, where command has to start with pingap as it does above.
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | sh
installs the latest release to /usr/local/bin/pingap on Linux and macOS (x86_64 and arm64). Variables in front of sh choose what is installed:
| Variable | Effect |
|---|---|
PINGAP_FULL=1 | The -full build, with every optional feature |
PINGAP_TLS=rustls | Linux: the -rustls-full build, without OpenSSL (see TLS backend) |
PINGAP_LIBC=gnu | Linux: the glibc build in place of the static musl one |
PINGAP_SERVICE=1 | Linux with systemd: also the pingap service and a starter configuration in /etc/pingap/conf; it is not enabled or started |
PINGAP_VERSION=0.15.0 | That release in place of the latest |
All assets are on the releases page.
# the certificate comes from Let's Encrypt
pingap --domain=pingap.io --upstream=192.168.1.1:3000
# or bring your own
pingap --domain=pingap.io --upstream=192.168.1.1:3000 --cert=/etc/ssl/pingap.io
--cert the certificate is ordered by HTTP-01: the domain has to resolve to this host, with port 80 reachable. It is kept in ~/.pingap/acme/<domains>.toml and used again at the next start. Do not delete it, issuing is rate limited.--cert is the certificate or the directory it is in (fullchain.pem / privkey.pem, cert.pem / key.pem and tls.crt / tls.key are found; --key names anything else). --upstream and --domain take lists separated by commas, --addr the address to listen on.--conf, which these flags cannot be combined with.[upstreams.api]
addrs = ["api.github.com:443"]
discovery = "dns"
sni = "api.github.com"
[plugins.staticServe]
category = "directory"
path = "~/Downloads"
[locations.github-api]
upstream = "api"
path = "/api"
proxy_set_headers = ["Host:api.github.com"]
rewrite = "^/api/(?<path>.+)$ /$1"
[locations.static]
plugins = ["staticServe"]
[servers.test]
addr = "127.0.0.1:6118"
locations = ["github-api", "static"]
The same can be written in HCL or KDL. Every key is described in the configuration reference.
--autoreload | A change is applied without a restart: within ten seconds from files, at once from etcd. What takes a restart is reported, and waits for one. The mode for containers |
-a, --autorestart | The same, and a restart that drops no request for what a reload cannot change, a listen address for one. For a daemon (-d) on Linux; anywhere else it reloads, and reports what waits |
-t | Builds every upstream, location, plugin, certificate and server as a start does, and binds nothing |
--strict | A key Pingap does not know, or one this build has no feature for, is an error, where it is otherwise a warning. For -t in CI |
--diff <other> | Prints what would change if <other> took the place of the configuration, credentials shown as checksums |
$ENV:NAME, $FILE:/path | As a whole value: replaced by the variable or the file when the configuration is loaded |