
Un proxy inverso como nginx, construido sobre pingora, simple y eficiente.
Antes de que la versión de pingap sea estable, no se aceptarán pull requests. Si tienes alguna pregunta, crea un nuevo issue primero.

Pingap es un proxy inverso de alto rendimiento impulsado por Cloudflare Pingora. Simplifica la gestión operativa al permitir la recarga en caliente dinámica y sin tiempo de inactividad de la configuración a través de archivos TOML concisos y una interfaz de administración web intuitiva.
Su fortaleza principal reside en un potente sistema de plugins, que ofrece más de veinte funciones listas para usar para Autenticación (JWT, Key Auth), Seguridad (CSRF, Restricciones de IP/Referer/UA), Control de Tráfico (Limitación de Tasa, Caching), Modificación de Contenido (Redirecciones, Sustitución de Contenido) y Observabilidad (ID de Solicitud). Esto hace de Pingap no solo un proxy, sino una puerta de enlace de aplicaciones flexible y extensible, diseñada para manejar sin esfuerzo escenarios complejos desde la protección de API hasta implementaciones modernas de aplicaciones web.
English Description | Documentación · Documentación en chino | Ejemplos | Plugins | Crates
flowchart LR
internet("Internet") -- solicitud --> 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"]
🚀 Alto Rendimiento y Fiabilidad
🔧 Dinámico y Fácil de Usar
🧩 Extensibilidad Poderosa
📊 Observabilidad Moderna
La forma más fácil de comenzar con Pingap es usando Docker Compose.
docker-compose.yml:# docker-compose.yml
version: '3.8'
services:
pingap:
image: vicanso/pingap:latest # Para producción, usa una versión específica como vicanso/pingap:0.12.1-full
container_name: pingap-instance
restart: always
ports:
- "80:80"
- "443:443"
volumes:
# Monta un directorio local para persistir todas las configuraciones y datos
- ./pingap_data:/opt/pingap
environment:
# Configurar usando variables de entorno
- PINGAP_CONF=/opt/pingap/conf
- PINGAP_ADMIN_ADDR=0.0.0.0:80/pingap
- PINGAP_ADMIN_USER=pingap
- PINGAP_ADMIN_PASSWORD=<TuContraseñaSegura> # ¡Cambia esto!
command:
# Inicia pingap y habilita la recarga en caliente
- pingap
- --autoreload
mkdir pingap_data
docker-compose up -d
¡Tu instancia de Pingap ya está funcionando! Puedes acceder a la interfaz web de administración en http://localhost/pingap con las credenciales que estableciste.
Para Linux y macOS, puedes instalar el último binario precompilado en /usr/local/bin/pingap con un solo comando:
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | sh
Variables de entorno opcionales:
PINGAP_FULL=1 — instala la compilación -full (todas las funciones opcionales habilitadas)PINGAP_LIBC=gnu — en Linux, usa la compilación glibc en lugar de la compilación estática musl predeterminada# Compilación con todas las funciones
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | PINGAP_FULL=1 sh
Destinos compatibles: Linux x86_64/arm64, Darwin x86_64/arm64. Consulta la página de versiones para todos los activos disponibles.
Para instrucciones más detalladas, incluyendo la ejecución desde un binario, consulta nuestra Documentación.
Un solo comando es suficiente para servir un dominio a través de https y reenviarlo a un backend:
# certificado solicitado a let's encrypt
pingap --domain=pingap.io --upstream=192.168.1.1:3000
# o usa tu propio certificado
pingap --domain=pingap.io --upstream=192.168.1.1:3000 --cert=/etc/ssl/pingap.io
Sin --cert, Pingap solicita un certificado a Let's Encrypt a través del
desafío HTTP-01, por lo que pingap.io debe resolverse a este host y el puerto 80 debe ser
accesible desde internet. El certificado emitido se guarda en
~/.pingap/acme/<domains>.toml y se reutiliza al reiniciar: la emisión tiene límite de tasa,
así que no lo elimines. Todo lo demás proviene de la línea de comandos: cambiar
--upstream surte efecto en el próximo inicio sin tocar el certificado.
--cert acepta el certificado en sí o el directorio que lo contiene; los diseños comunes
fullchain.pem / privkey.pem, cert.pem / key.pem y tls.crt / tls.key
se detectan automáticamente, usa --key para cualquier otro caso. El listener
predeterminado es 0.0.0.0:443 cuando hay un certificado y 0.0.0.0:80 cuando no hay
ni certificado ni dominio, y --addr lo anula. --upstream
toma una lista separada por comas de backends, --domain una lista separada por comas de
hosts (omítelo para servir a todos los hosts a través de http simple).
La configuración se genera en cada inicio, por lo que no se puede editar a través
de la interfaz de administración: para algo más que un solo servidor usa --conf, que no se puede
combinar con estos indicadores.
Pingap está diseñado para adaptarse a los cambios de configuración sin tiempo de inactividad.
Recarga en Caliente (--autoreload): Para la mayoría de los cambios, como actualizar upstreams, ubicaciones o plugins, Pingap aplica la nueva configuración en 10 segundos sin reiniciar. Este es el modo recomendado para entornos contenedorizados.
Reinicio Gradual (-a o --autorestart): Para cambios fundamentales (como modificar los puertos de escucha del servidor), este modo realiza un reinicio completo sin tiempo de inactividad, asegurando que no se pierdan solicitudes.
make dev
Si necesitas una interfaz de administración web, debes instalar nodejs y construir los assets web.
# generar asset de administración web
cd web
npm i
cd ..
make build-web
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"]
Puedes encontrar las instrucciones relevantes aquí: https://pingap.io/crates/config.
graph TD;
server["Servidor HTTP"];
locationA["Ubicación A"];
locationB["Ubicación B"];
locationPluginListA["Lista de Plugins Proxy A"];
locationPluginListB["Lista de Plugins Proxy B"];
upstreamA1["Upstream A1"];
upstreamA2["Upstream A2"];
upstreamB1["Upstream B1"];
upstreamB2["Upstream B2"];
locationResponsePluginListA["Lista de Plugins de Respuesta A"];
locationResponsePluginListB["Lista de Plugins de Respuesta B"];
start("Nueva Solicitud") --> server
server -- "host:HostA, Path:/api/*" --> locationA
server -- "Path:/rest/*"--> locationB
locationA -- "Ejecutar Plugins Proxy" --> locationPluginListA
locationB -- "Ejecutar Plugins Proxy" --> locationPluginListB
locationPluginListA -- "proxy pass: 10.0.0.1:8001" --> upstreamA1
locationPluginListA -- "proxy pass: 10.0.0.2:8001" --> upstreamA2
locationPluginListA -- "hecho" --> response
locationPluginListB -- "proxy pass: 10.0.0.1:8002" --> upstreamB1
locationPluginListB -- "proxy pass: 10.0.0.2:8002" --> upstreamB2
locationPluginListB -- "hecho" --> response
upstreamA1 -- "Ejecutar Plugins de Respuesta" --> locationResponsePluginListA
upstreamA2 -- "Ejecutar Plugins de Respuesta" --> locationResponsePluginListA
upstreamB1 -- "Ejecutar Plugins de Respuesta" --> locationResponsePluginListB
upstreamB2 -- "Ejecutar Plugins de Respuesta" --> locationResponsePluginListB
locationResponsePluginListA --> response
locationResponsePluginListB --> response
response["Respuesta HTTP"] --> stop("Registro");
CPU: M4 Pro, Hilo: 1
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
Nuestro MSRV actual es 1.88
Este proyecto está licenciado bajo Apache License, Version 2.0.