
pingap v0.1.3.6
Ein Reverse-Proxy wie nginx, basierend auf pingora, einfach und effizient.
pingap
Bevor die Version von pingap stabil ist, werden keine Pull Requests akzeptiert. Wenn Sie Fragen haben, erstellen Sie bitte zuerst ein neues Issue.

Überblick
Pingap ist ein leistungsstarker Reverse-Proxy, der auf Cloudflare Pingora basiert. Er vereinfacht das Betriebsmanagement durch dynamisches, unterbrechungsfreies Hot-Reloading der Konfiguration über prägnante TOML-Dateien und eine intuitive Weboberfläche.
Seine Kernstärke liegt in einem leistungsfähigen Plugin-System mit über zwanzig integrierten Funktionen für Authentifizierung (JWT, Key Auth), Sicherheit (CSRF, IP/Referer/UA-Beschränkungen), Verkehrssteuerung (Rate Limiting, Caching), Inhaltsänderung (Weiterleitungen, Inhaltsersetzung) und Beobachtbarkeit (Request ID). Damit ist Pingap nicht nur ein Proxy, sondern ein flexibles und erweiterbares Anwendungs-Gateway, das mühelos komplexe Szenarien vom API-Schutz bis hin zu modernen Webanwendungsbereitstellungen bewältigt.
中文说明 | Dokumentation · 中文文档 | Beispiele | 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"]
Hauptfunktionen
-
🚀 Hohe Leistung & Zuverlässigkeit
- In Rust entwickelt für Speichersicherheit und Spitzenleistung.
- Basierend auf Cloudflare Pingora, einer praxiserprobten asynchronen Netzwerkbibliothek.
- Unterstützt HTTP/1.1, HTTP/2 und gRPC-Web-Proxy.
-
🔧 Dynamisch & benutzerfreundlich
- Unterbrechungsfreie Konfigurationsänderungen mit Hot-Reloading.
- Einfache, lesbare TOML-Konfigurationsdateien.
- Voll ausgestattete Weboberfläche für intuitive Echtzeitverwaltung.
- Unterstützt sowohl Dateien als auch etcd als Konfigurations-Backends.
- Unterstützt Konfigurationsverlauf, der mit einem Klick auf eine frühere Version wiederhergestellt werden kann.
-
🧩 Leistungsstarke Erweiterbarkeit
- Ein umfangreiches Plugin-System für gängige Gateway-Aufgaben.
- Erweitertes Routing mit Host-, Pfad- und Regex-Abgleich.
- Integrierte Service-Discovery über statische Listen, DNS oder Docker-Labels.
- Automatisiertes HTTPS mit Let's Encrypt (unterstützt sowohl HTTP-01- als auch DNS-01-Challenges).
-
📊 Moderne Beobachtbarkeit
- Native Prometheus-Metriken für Monitoring (Pull- & Push-Modi).
- Integrierte OpenTelemetry-Unterstützung für verteiltes Tracing.
- Hochgradig anpassbare Zugriffsprotokolle mit über 30 Variablen.
- Detaillierte Leistungsmetriken, einschließlich Upstream-Verbindungszeit, Verarbeitungszeit und mehr.
🚀 Erste Schritte
Der einfachste Weg, mit Pingap zu starten, ist die Verwendung von Docker Compose.
- Erstellen Sie eine
docker-compose.yml-Datei:
# docker-compose.yml
version: '3.8'
services:
pingap:
image: vicanso/pingap:latest # Für die Produktion eine bestimmte Version verwenden, z. B. vicanso/pingap:0.12.1-full
container_name: pingap-instance
restart: always
ports:
- "80:80"
- "443:443"
volumes:
# Ein lokales Verzeichnis einhängen, um alle Konfigurationen und Daten zu speichern
- ./pingap_data:/opt/pingap
environment:
# Konfiguration über Umgebungsvariablen
- PINGAP_CONF=/opt/pingap/conf
- PINGAP_ADMIN_ADDR=0.0.0.0:80/pingap
- PINGAP_ADMIN_USER=pingap
- PINGAP_ADMIN_PASSWORD=<YourSecurePassword> # Ändern Sie dies!
command:
# Pingap starten und Hot-Reloading aktivieren
- pingap
- --autoreload
- Erstellen Sie ein Datenverzeichnis und führen Sie es aus:
mkdir pingap_data
docker-compose up -d
- Zugriff auf die Admin-Oberfläche:
Ihre Pingap-Instanz läuft jetzt! Sie können auf die Weboberfläche unter http://localhost/pingap mit den von Ihnen festgelegten Anmeldedaten zugreifen.
Binärdatei per curl installieren
Für Linux und macOS können Sie die neueste vorgefertigte Binärdatei mit einem Befehl in /usr/local/bin/pingap installieren:
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | sh
Optionale Umgebungsvariablen:
PINGAP_FULL=1— installiert den-full-Build (alle optionalen Funktionen aktiviert)PINGAP_LIBC=gnu— unter Linux den glibc-Build anstelle des standardmäßigen statischen musl-Builds verwendenPINGAP_TLS=rustls— unter Linux den-rustls-full-Build installieren (rustls-TLS-Backend, alle optionalen Funktionen, kein OpenSSL); siehe TLS-Backend
# Voll ausgestatteter Build
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | PINGAP_FULL=1 sh
Unterstützte Ziele: Linux x86_64/arm64, Darwin x86_64/arm64. Alle verfügbaren Assets finden Sie auf der Releases-Seite.
Für detailliertere Anweisungen, einschließlich der Ausführung über eine Binärdatei, lesen Sie unsere Dokumentation.
Einen Proxy ohne Konfigurationsdatei starten
Ein einziger Befehl genügt, um eine Domain über HTTPS zu bedienen und an ein Backend weiterzuleiten:
# Zertifikat von Let's Encrypt angefordert
pingap --domain=pingap.io --upstream=192.168.1.1:3000
# oder eigenes Zertifikat mitbringen
pingap --domain=pingap.io --upstream=192.168.1.1:3000 --cert=/etc/ssl/pingap.io
Ohne --cert fordert Pingap ein Zertifikat von Let's Encrypt über die
HTTP-01-Challenge an, daher muss pingap.io auf diesen Host auflösen und Port 80
vom Internet aus erreichbar sein. Das ausgestellte Zertifikat wird in
~/.pingap/acme/<domains>.toml gespeichert und beim Neustart wiederverwendet — die Ausstellung ist
ratenbegrenzt, daher nicht löschen. Alles andere kommt weiterhin von der Befehlszeile: Eine Änderung
von --upstream wird beim nächsten Start wirksam, ohne das Zertifikat zu berühren.
--cert akzeptiert das Zertifikat selbst oder das Verzeichnis, das es enthält — die gängigen
Layouts fullchain.pem / privkey.pem, cert.pem / key.pem und tls.crt / tls.key
werden automatisch erkannt, für alles andere --key verwenden. Der Listener
lautet standardmäßig auf 0.0.0.0:443, wenn ein Zertifikat vorhanden ist, und auf 0.0.0.0:80, wenn weder
ein Zertifikat noch eine Domain vorhanden ist; --addr überschreibt dies. --upstream
akzeptiert eine durch Kommas getrennte Liste von Backends, --domain eine durch Kommas getrennte Liste von
Hosts (weglassen, um jeden Host über einfaches HTTP zu bedienen). Anfragen für einen Host,
der nicht aufgeführt ist, werden mit 404 beantwortet.
Die Konfiguration wird bei jedem Start generiert und kann daher nicht über die
Admin-Oberfläche bearbeitet werden: Für alles über einen einzelnen Server hinaus --conf verwenden, das
nicht mit diesen Flags kombiniert werden kann.
Dynamische Konfiguration
Pingap ist darauf ausgelegt, sich ohne Ausfallzeiten an Konfigurationsänderungen anzupassen.
Hot Reload (--autoreload): Für die meisten Änderungen — wie das Aktualisieren von Upstreams, Locations oder Plugins — wendet Pingap die neue Konfiguration innerhalb von 10 Sekunden ohne Neustart an. Dies ist der empfohlene Modus für Container-Umgebungen.
Graceful Restart (-a oder --autorestart): Für grundlegende Änderungen (wie das Ändern von Server-Listen-Ports) führt dieser Modus einen vollständigen, unterbrechungsfreien Neustart durch, sodass keine Anfragen verworfen werden.
Die Übergabe erfolgt readiness-gesteuert und nicht zeitgesteuert: Der Ersatz wird mit -d -u gestartet, meldet sich über einen Unix-Socket neben dem Upgrade-Socket zurück, sobald er bereit ist, die Listener zu übernehmen, und erst dann sendet sich der laufende Prozess selbst SIGQUIT. Wenn der Ersatz beendet wird, sein Daemon stirbt oder basic.restart_ready_timeout (Standard 1m) zuerst abläuft, wird der Neustart abgebrochen und der laufende Prozess bedient weiterhin.
🔧 Entwicklung
make dev
Wenn Sie eine Weboberfläche benötigen, sollten Sie nodejs installieren und die Web-Assets erstellen.
# Admin-Web-Asset generieren
cd web
npm i
cd ..
make build-web
TLS-Backend
Der Standard-Build beendet TLS mit OpenSSL, das von der openssl-Crate aus dem Quellcode kompiliert wird. Um stattdessen mit rustls zu bauen, das den OpenSSL-Quellcode-Build weglässt (ein C-Compiler wird weiterhin benötigt: Die Krypto-Provider von rustls, ring und aws-lc-rs, enthalten C und Assembly):
cargo build --release --no-default-features --features tls-rustls
# auch mit den optionalen Funktionen
cargo build --release --no-default-features --features tls-rustls,full
Der rustls-Build ignoriert die pro-Server-Einstellungen tls_min_version, tls_max_version, tls_cipher_list und tls_ciphersuites und protokolliert eine Warnung, wenn sie gesetzt sind: Er bietet immer TLS 1.2 und 1.3 mit den Standard-Cipher-Suites von rustls an. Alles andere, einschließlich dynamischer SNI-Zertifikate, Ausstellung selbstsignierter CAs, ACME und der Upstream-ca-Option, verhält sich gleich. Ein Unterschied bei der Verifizierung von Upstreams: rustls (webpki) lehnt ein Serverzertifikat mit CA:TRUE ab, das OpenSSL akzeptiert. Ein Backend, das ein schnelles selbstsigniertes Zertifikat von openssl req -x509 verwendet, benötigt daher ein ordnungsgemäßes Blatt, das von einer CA signiert ist (oder ein selbstsigniertes Blatt ohne das CA-Flag), bevor die Upstream-ca-Option ihm vertrauen kann. Das Startprotokoll meldet, mit welchem Backend eine Binärdatei erstellt wurde.
📝 Konfiguration
server "test" {
addr = "127.0.0.1:6118"
location "github-api" {
path = "/api"
proxy_set_headers = ["Host:api.github.com"]
rewrite = "^/api/(?<path>.+)$ /$1"
upstream "api" {
addrs = ["api.github.com:443"]
discovery = "dns"
sni = "api.github.com"
}
}
location "static" {
plugin "staticServe" {
category = "directory"
path = "~/Downloads"
step = "request"
}
}
}
[upstreams.api]
addrs = ["api.github.com:443"]
discovery = "dns"
sni = "api.github.com"
[plugins.staticServe]
category = "directory"
path = "~/Downloads"
step = "request"
[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"]
Die entsprechenden Anweisungen finden Sie hier: https://pingap.io/crates/config.
🔄 Proxy-Schritt
graph TD;
server["HTTP Server"];
locationA["Location A"];
locationB["Location B"];
locationPluginListA["Proxy Plugin List A"];
locationPluginListB["Proxy Plugin List B"];
upstreamA1["Upstream A1"];
upstreamA2["Upstream A2"];
upstreamB1["Upstream B1"];
upstreamB2["Upstream B2"];
locationResponsePluginListA["Response Plugin List A"];
locationResponsePluginListB["Response Plugin List B"];
start("New Request") --> server
server -- "host:HostA, Path:/api/*" --> locationA
server -- "Path:/rest/*"--> locationB
locationA -- "Exec Proxy Plugins" --> locationPluginListA
locationB -- "Exec Proxy Plugins" --> locationPluginListB
locationPluginListA -- "proxy pass: 10.0.0.1:8001" --> upstreamA1
locationPluginListA -- "proxy pass: 10.0.0.2:8001" --> upstreamA2
locationPluginListA -- "done" --> response
locationPluginListB -- "proxy pass: 10.0.0.1:8002" --> upstreamB1
locationPluginListB -- "proxy pass: 10.0.0.2:8002" --> upstreamB2
locationPluginListB -- "done" --> response
upstreamA1 -- "Exec Response Plugins" --> locationResponsePluginListA
upstreamA2 -- "Exec Response Plugins" --> locationResponsePluginListA
upstreamB1 -- "Exec Response Plugins" --> locationResponsePluginListB
upstreamB2 -- "Exec Response Plugins" --> locationResponsePluginListB
locationResponsePluginListA --> response
locationResponsePluginListB --> response
response["HTTP Response"] --> stop("Logging");
📊 Leistung
CPU: M4 Pro, Thread: 1
Ping ohne Zugriffsprotokoll
wrk 'http://127.0.0.1:6118/ping' --latency
Running 10s test @ http://127.0.0.1:6118/ping
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 66.41us 23.67us 1.11ms 76.54%
Req/Sec 73.99k 2.88k 79.77k 68.81%
Latency Distribution
50% 67.00us
75% 80.00us
90% 91.00us
99% 116.00us
1487330 requests in 10.10s, 194.32MB read
Requests/sec: 147260.15
Transfer/sec: 19.24MB
📦 Rust-Version
Unsere aktuelle MSRV ist 1.96
📄 Lizenz
Dieses Projekt ist unter der Apache License, Version 2.0 lizenziert.