Volver a actualizaciones
Nuevo releaseJul 27, 2026

pingap v0.13.7

Un proxy inverso como nginx, construido sobre pingora, simple y eficiente.

Compartir

pingap

Antes de que la versión de pingap sea estable, no se aceptarán pull requests. Si tienes alguna pregunta, crea primero un nuevo issue.

Pingap Logo

Resumen

Pingap es un proxy inverso de alto rendimiento impulsado por Cloudflare Pingora. Simplifica la gestión operativa al permitir una recarga dinámica de configuración sin tiempo de inactividad mediante 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 (Límite de Tasa, Caché), Modificación de Contenido (Redirecciones, Sustitución de Contenido) y Observabilidad (ID de Solicitud). Esto convierte a Pingap no solo en un proxy, sino en 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.

中文说明 | Documentación · 中文文档 | Ejemplos | 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"]

Características Principales

  • 🚀 Alto Rendimiento y Fiabilidad

    • Construido con Rust para seguridad de memoria y rendimiento de primer nivel.
    • Impulsado por Cloudflare Pingora, una biblioteca de redes asíncronas probada en batalla.
    • Soporta proxy HTTP/1.1, HTTP/2 y gRPC-web.
  • 🔧 Dinámico y Fácil de Usar

    • Cambios de configuración sin tiempo de inactividad con recarga en caliente.
    • Archivos de configuración TOML simples y legibles.
    • Interfaz web completa para una gestión intuitiva y en tiempo real.
    • Soporta tanto archivos como etcd como backends de configuración.
    • Soporta registro del historial de configuración, pudiendo restaurar a la versión histórica con un clic.
  • 🧩 Extensibilidad Potente

    • Un rico sistema de plugins para manejar tareas comunes de puerta de enlace.
    • Enrutamiento avanzado con coincidencia de host, ruta y regex.
    • Descubrimiento de servicios integrado mediante listas estáticas, DNS o etiquetas de Docker.
    • HTTPS automatizado con Let's Encrypt (soporta tanto desafíos HTTP-01 como DNS-01).
  • 📊 Observabilidad Moderna

    • Métricas nativas de Prometheus para monitoreo (modos pull y push).
    • Soporte integrado de OpenTelemetry para trazado distribuido.
    • Registros de acceso altamente personalizables con más de 30 variables.
    • Métricas de rendimiento detalladas, incluyendo tiempo de conexión al upstream, tiempo de procesamiento y más.

🚀 Primeros Pasos

La forma más fácil de comenzar con Pingap es usando Docker Compose.

  1. Crea un archivo 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:
      # Configura 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=<YourSecurePassword> # ¡Cambia esto!
    command:
      # Inicia pingap y habilita la recarga en caliente
      - pingap
      - --autoreload
  1. Crea un directorio de datos y ejecuta:
mkdir pingap_data
docker-compose up -d
  1. Accede a la interfaz de administración:

¡Tu instancia de Pingap ya está en ejecución! Puedes acceder a la interfaz de administración web en http://localhost/pingap con las credenciales que configuraste.

Instalar el binario mediante curl

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
  • PINGAP_TLS=rustls — en Linux, instala la compilación -rustls-full (backend TLS rustls, todas las funciones opcionales, sin OpenSSL); consulta backend TLS
# Compilación con todas las funciones
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | PINGAP_FULL=1 sh

Objetivos soportados: Linux x86_64/arm64, Darwin x86_64/arm64. Consulta la página de releases para ver todos los recursos disponibles.

Para instrucciones más detalladas, incluyendo la ejecución desde un binario, consulta nuestra Documentación.

Iniciar un proxy sin archivo de configuració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 mediante el 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 tiene efecto en el siguiente 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 otra cosa. El listener por defecto 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 acepta una lista separada por comas de backends, --domain una lista separada por comas de hosts (omítelo para servir cada host a través de http simple). Las solicitudes para un host que no esté en la lista reciben una respuesta 404.

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 cualquier cosa más allá de un solo servidor usa --conf, que no se puede combinar con estas banderas.

Configuración Dinámica

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, locations o plugins — Pingap aplica la nueva configuración en 10 segundos sin reiniciar. Este es el modo recomendado para entornos containerizados.

Reinicio Elegante (-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 pierda ninguna solicitud.

La transferencia está impulsada por la preparación en lugar de por tiempo: el reemplazo se inicia con -d -u, informa a través de un socket unix junto al socket de actualización en el momento en que está listo para hacerse cargo de los listeners, y solo entonces el proceso en ejecución se envía SIGQUIT. Si el reemplazo sale, su daemon muere, o basic.restart_ready_timeout (por defecto 1m) pasa primero, el reinicio se abandona y el proceso en ejecución continúa sirviendo.

🔧 Desarrollo

make dev

Si necesitas un administrador web, debes instalar nodejs y compilar los assets web.

# genera el asset web de administración
cd web
npm i 
cd ..
make build-web

Backend TLS

La compilación predeterminada termina TLS con OpenSSL, compilado desde el código fuente por el crate openssl. Para compilar con rustls en su lugar, que elimina la compilación de código fuente de OpenSSL (aún se necesita un compilador C: los proveedores criptográficos de rustls, ring y aws-lc-rs, contienen C y ensamblador):

cargo build --release --no-default-features --features tls-rustls
# con las funciones opcionales también
cargo build --release --no-default-features --features tls-rustls,full

La compilación rustls ignora las configuraciones por servidor tls_min_version, tls_max_version, tls_cipher_list y tls_ciphersuites y registra una advertencia cuando están configuradas: siempre ofrece TLS 1.2 y 1.3 con los conjuntos de cifrado predeterminados de rustls. Todo lo demás, incluyendo certificados SNI dinámicos, emisión de CA autofirmada, ACME y la opción ca del upstream, se comporta igual. Una diferencia a tener en cuenta al verificar upstreams: rustls (webpki) rechaza un certificado de servidor que lleva CA:TRUE, que OpenSSL acepta, por lo que un backend que usa un certificado autofirmado rápido openssl req -x509 necesita una hoja adecuada firmada por una CA (o una hoja autofirmada sin la bandera CA) antes de que la opción ca del upstream pueda confiar en él. El registro de inicio informa con qué backend se compiló un binario.

📝 Configuración

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.

🔄 Paso de 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");

📊 Rendimiento

CPU: M4 Pro, Thread: 1

Ping sin registro de acceso

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

📦 Versión de Rust

Nuestro MSRV actual es 1.96

📄 Licencia

Este proyecto está licenciado bajo Apache License, Version 2.0.

Categorías