
pingap v0.13.10
Un reverse proxy comme nginx, construit sur pingora, simple et efficace.
pingap
Avant que la version de pingap ne soit stable, aucune pull request ne sera acceptée. Si vous avez des questions, veuillez d'abord créer un nouveau ticket (issue).

Présentation
Pingap est un reverse proxy haute performance propulsé par Cloudflare Pingora. Il simplifie la gestion opérationnelle en permettant un rechargement dynamique de la configuration sans interruption de service, via des fichiers TOML concis et une interface d'administration web intuitive.
Sa force principale réside dans un puissant système de plugins, offrant plus de vingt fonctionnalités prêtes à l'emploi pour l'authentification (JWT, Key Auth), la sécurité (CSRF, restrictions IP/Référent/UA), le contrôle du trafic (limitation de débit, mise en cache), la modification de contenu (redirections, substitution de contenu) et l'observabilité (Request ID). Cela fait de Pingap non seulement un proxy, mais aussi une passerelle applicative flexible et extensible, conçue pour gérer sans effort des scénarios complexes, de la protection d'API aux déploiements d'applications web modernes.
中文说明 | Documentation · 中文文档 | Exemples | 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"]
Principales fonctionnalités
-
🚀 Haute performance et fiabilité
- Conçu en Rust pour la sécurité mémoire et des performances de premier ordre.
- Propulsé par Cloudflare Pingora, une bibliothèque réseau asynchrone éprouvée en conditions réelles.
- Prend en charge le proxy HTTP/1.1, HTTP/2 et gRPC-web.
-
🔧 Dynamique et facile à utiliser
- Modifications de configuration sans interruption de service grâce au rechargement à chaud.
- Fichiers de configuration TOML simples et lisibles.
- Interface web complète pour une gestion intuitive en temps réel.
- Prise en charge de deux backends de configuration : fichiers et etcd.
- Historique des configurations avec restauration en un clic vers une version antérieure.
-
🧩 Extensibilité puissante
- Un riche système de plugins pour gérer les tâches courantes de passerelle.
- Routage avancé avec correspondance par hôte, chemin et regex.
- Découverte de services intégrée via listes statiques, DNS ou labels Docker.
- HTTPS automatisé avec Let's Encrypt (prise en charge des défis HTTP-01 et DNS-01).
-
📊 Observabilité moderne
- Métriques Prometheus natives pour la surveillance (modes pull et push).
- Prise en charge intégrée d'OpenTelemetry pour le tracing distribué.
- Journaux d'accès hautement personnalisables avec plus de 30 variables.
- Métriques de performance détaillées, notamment le temps de connexion en amont, le temps de traitement, etc.
🚀 Pour commencer
Le moyen le plus simple de démarrer avec Pingap est d'utiliser Docker Compose.
- Créez un fichier
docker-compose.yml:
# 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
- Créez un répertoire de données et lancez :
mkdir pingap_data
docker-compose up -d
- Accédez à l'interface d'administration :
Votre instance Pingap est maintenant opérationnelle ! Vous pouvez accéder à l'interface d'administration web à l'adresse http://localhost/pingap avec les identifiants que vous avez définis.
Installer le binaire via curl
Pour Linux et macOS, vous pouvez installer le dernier binaire précompilé dans /usr/local/bin/pingap avec une seule commande :
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | sh
Variables d'environnement optionnelles :
PINGAP_FULL=1— installe la version-full(toutes les fonctionnalités optionnelles activées)PINGAP_LIBC=gnu— sur Linux, utilise la version glibc au lieu de la version statique musl par défaut
# Version complète
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | PINGAP_FULL=1 sh
Cibles prises en charge : Linux x86_64/arm64, Darwin x86_64/arm64. Consultez la page des releases pour tous les éléments disponibles.
Pour des instructions plus détaillées, y compris l'exécution à partir d'un binaire, consultez notre Documentation.
Démarrer un proxy sans fichier de configuration
Une seule commande suffit pour servir un domaine en https et le rediriger vers un backend :
# certificat demandé auprès de let's encrypt
pingap --domain=pingap.io --upstream=192.168.1.1:3000
# ou utilisez votre propre certificat
pingap --domain=pingap.io --upstream=192.168.1.1:3000 --cert=/etc/ssl/pingap.io
Sans --cert, Pingap demande un certificat à Let's Encrypt via le défi
HTTP-01. pingap.io doit donc résoudre vers cet hôte et le port 80 doit être
accessible depuis Internet. Le certificat émis est conservé dans
~/.pingap/acme/<domains>.toml et réutilisé au redémarrage — l'émission est
limitée en débit, ne le supprimez donc pas. Tout le reste provient de la ligne
de commande : modifier --upstream prend effet au prochain démarrage sans
toucher au certificat.
--cert accepte le certificat lui-même ou le répertoire qui le contient — les
dispositions courantes fullchain.pem / privkey.pem, cert.pem / key.pem
et tls.crt / tls.key sont détectées automatiquement ; utilisez --key pour
tout autre cas. L'écouteur écoute par défaut sur 0.0.0.0:443 lorsqu'un
certificat est présent et sur 0.0.0.0:80 lorsqu'il n'y a ni certificat ni
domaine ; --addr permet de le remplacer. --upstream accepte une liste de
backends séparés par des virgules, --domain une liste d'hôtes séparés par des
virgules (omettez-le pour servir tous les hôtes en http simple).
La configuration est générée à chaque démarrage, elle ne peut donc pas être
modifiée via l'interface d'administration : pour tout ce qui va au-delà d'un
serveur unique, utilisez --conf, qui ne peut pas être combiné avec ces
options.
Configuration dynamique
Pingap est conçu pour s'adapter aux changements de configuration sans interruption de service.
Rechargement à chaud (--autoreload) : pour la plupart des modifications — comme la mise à jour des upstreams, des locations ou des plugins — Pingap applique la nouvelle configuration en moins de 10 secondes sans redémarrage. C'est le mode recommandé pour les environnements conteneurisés.
Redémarrage gracieux (-a ou --autorestart) : pour les changements fondamentaux (comme la modification des ports d'écoute du serveur), ce mode effectue un redémarrage complet sans interruption de service, garantissant qu'aucune requête n'est perdue.
🔧 Développement
make dev
Si vous avez besoin d'une interface d'administration web, vous devez installer nodejs et compiler les ressources web.
# générer les ressources web d'administration
cd web
npm i
cd ..
make build-web
📝 Configuration
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"]
Vous trouverez les instructions correspondantes ici : https://pingap.io/crates/config.
🔄 Étapes du proxy
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");
📊 Performance
CPU : M4 Pro, Thread : 1
Ping sans journal d'accès
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
📦 Version de Rust
Notre MSRV actuel est 1.88
📄 Licence
Ce projet est sous licence Apache License, Version 2.0.