
Um proxy reverso como o nginx, construído sobre pingora, simples e eficiente.
Antes que a versão do pingap esteja estável, nenhum pull request será aceito. Se você tiver alguma dúvida, crie uma nova issue primeiro.

O Pingap é um proxy reverso de alta performance desenvolvido com o Cloudflare Pingora. Ele simplifica a gestão operacional ao permitir recarga dinâmica de configuração sem tempo de inatividade por meio de arquivos TOML concisos e uma interface de administração web intuitiva.
Seu principal ponto forte está em um poderoso sistema de plugins, oferecendo mais de vinte recursos prontos para uso em Autenticação (JWT, Key Auth), Segurança (CSRF, Restrições de IP/Referer/UA), Controle de Tráfego (Limitação de Taxa, Cache), Modificação de Conteúdo (Redirecionamentos, Substituição de Conteúdo) e Observabilidade (ID de Requisição). Isso torna o Pingap não apenas um proxy, mas um gateway de aplicação flexível e extensível, projetado para lidar sem esforço com cenários complexos, desde proteção de APIs até implantações modernas de aplicações web.
中文说明 | Documentação · 中文文档 | Exemplos | 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"]🚀 Alta Performance e Confiabilidade
🔧 Dinâmico e Fácil de Usar
🧩 Extensibilidade Poderosa
📊 Observabilidade Moderna
A maneira mais fácil de começar com o Pingap é usando o Docker Compose.
docker-compose.yml:# docker-compose.yml
version: '3.8'
services:
pingap:
image: vicanso/pingap:latest # Para produção, use uma versão específica como vicanso/pingap:0.12.1-full
container_name: pingap-instance
restart: always
ports:
- "80:80"
- "443:443"
volumes:
# Monte um diretório local para persistir todas as configurações e dados
- ./pingap_data:/opt/pingap
environment:
# Configure usando variáveis de ambiente
- PINGAP_CONF=/opt/pingap/conf
- PINGAP_ADMIN_ADDR=0.0.0.0:80/pingap
- PINGAP_ADMIN_USER=pingap
- PINGAP_ADMIN_PASSWORD=<YourSecurePassword> # Altere isto!
command:
# Inicie o pingap e habilite a recarga a quente
- pingap
- --autoreload
mkdir pingap_data
docker-compose up -d
Sua instância do Pingap está agora em execução! Você pode acessar a interface de administração web em http://localhost/pingap com as credenciais que você definiu.
Para Linux e macOS, você pode instalar o binário pré-compilado mais recente em /usr/local/bin/pingap com um único comando:
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | sh
Variáveis de ambiente opcionais:
PINGAP_FULL=1 — instala a compilação -full (todos os recursos opcionais habilitados)PINGAP_LIBC=gnu — no Linux, usa a compilação glibc em vez da compilação estática musl padrãoPINGAP_TLS=rustls — no Linux, instala a compilação -rustls-full (backend TLS rustls, todos os recursos opcionais, sem OpenSSL); veja backend TLS# Compilação com todos os recursos
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | PINGAP_FULL=1 sh
Plataformas suportadas: Linux x86_64/arm64, Darwin x86_64/arm64. Consulte a página de releases para todos os artefatos disponíveis.
Para instruções mais detalhadas, incluindo execução a partir de um binário, consulte nossa Documentação.
Um único comando é suficiente para servir um domínio via https e encaminhá-lo para um backend:
# certificado solicitado ao let's encrypt
pingap --domain=pingap.io --upstream=192.168.1.1:3000
# ou use seu próprio certificado
pingap --domain=pingap.io --upstream=192.168.1.1:3000 --cert=/etc/ssl/pingap.io
Sem --cert, o Pingap solicita um certificado ao Let's Encrypt por meio do
desafio HTTP-01, portanto pingap.io deve resolver para este host e a porta 80 deve
estar acessível pela internet. O certificado emitido é mantido em
~/.pingap/acme/<domains>.toml e reutilizado na reinicialização — a emissão tem limite de taxa,
portanto não o exclua. Todo o resto ainda vem da linha de comando: alterar
--upstream tem efeito na próxima inicialização sem tocar no certificado.
--cert aceita o próprio certificado ou o diretório que o contém — os layouts comuns
fullchain.pem / privkey.pem, cert.pem / key.pem e tls.crt / tls.key
são detectados automaticamente; use --key para qualquer outra coisa. O listener
padrão é 0.0.0.0:443 quando há um certificado e 0.0.0.0:80 quando não há
nem certificado nem domínio, e --addr o substitui. --upstream
aceita uma lista separada por vírgulas de backends, --domain uma lista separada por
vírgulas de hosts (omita-o para servir todos os hosts via http simples). Requisições para um host que
não está listado recebem resposta 404.
A configuração é gerada a cada inicialização, portanto não pode ser editada por meio
da interface de administração: para qualquer coisa além de um único servidor, use --conf, que não pode ser
combinado com essas flags.
O Pingap é projetado para se adaptar a alterações de configuração sem tempo de inatividade.
Recarga a Quente (--autoreload): Para a maioria das alterações — como atualizar upstreams, locations ou plugins — o Pingap aplica a nova configuração em até 10 segundos sem reinicialização. Este é o modo recomendado para ambientes conteinerizados.
Reinicialização Graciosa (-a ou --autorestart): Para alterações fundamentais (como modificar portas de escuta do servidor), este modo executa uma reinicialização completa, sem tempo de inatividade, garantindo que nenhuma requisição seja descartada.
A transferência é orientada por prontidão, não por tempo: o substituto é iniciado com -d -u, reporta de volta por um unix socket ao lado do socket de upgrade no momento em que está pronto para assumir os listeners, e somente então o processo em execução envia SIGQUIT a si mesmo. Se o substituto sair, seu daemon morrer ou basic.restart_ready_timeout (padrão 1m) expirar primeiro, a reinicialização é abandonada e o processo em execução continua servindo.
make dev
Se você precisar de um administrador web, deve instalar o nodejs e compilar os assets web.
# gerar asset web do administrador
cd web
npm i
cd ..
make build-web
A compilação padrão termina TLS com OpenSSL, compilado a partir do código-fonte pelo crate openssl. Para compilar com rustls em vez disso, o que elimina a compilação do código-fonte do OpenSSL (um compilador C ainda é necessário: os provedores criptográficos do rustls, ring e aws-lc-rs, contêm C e assembly):
cargo build --release --no-default-features --features tls-rustls
# com os recursos opcionais também
cargo build --release --no-default-features --features tls-rustls,full
A compilação rustls ignora as configurações por servidor tls_min_version, tls_max_version, tls_cipher_list e tls_ciphersuites e registra um aviso quando elas são definidas: ela sempre oferece TLS 1.2 e 1.3 com os conjuntos de cifras padrão do rustls. Todo o resto, incluindo certificados SNI dinâmicos, emissão de CA autoassinada, ACME e a opção ca do upstream, se comporta da mesma forma. Uma diferença a conhecer ao verificar upstreams: o rustls (webpki) rejeita um certificado de servidor que carrega CA:TRUE, que o OpenSSL aceita, portanto um backend que usa um certificado autoassinado rápido openssl req -x509 precisa de uma folha adequada assinada por uma CA (ou uma folha autoassinada sem o flag CA) antes que a opção ca do upstream possa confiar nele. O log de inicialização informa com qual backend o binário foi compilado.
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"]
Você pode encontrar as instruções relevantes aqui: https://pingap.io/crates/config.
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");CPU: M4 Pro, Thread: 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
Nosso MSRV atual é 1.96
Este projeto é licenciado sob Apache License, Version 2.0.