Proxy de WebSocket com Nginx
WebSocket exige configuração especial no Nginx — diferente de HTTP, o protocolo é persistente e requer o mecanismo de upgrade de conexão. Sem a configuração correta, o Nginx fecha a conexão WebSocket após um timeout curto ou retorna 502. Com os headers de upgrade e os timeouts corretos, o proxy funciona transparentemente.
Configuração básica de proxy WebSocket
Headers essenciais para o upgrade de protocolo HTTP → WebSocket:
# /etc/nginx/conf.d/websocket.conf
# Map para suportar WebSocket upgrade
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl http2;
server_name api.seudominio.com.br;
ssl_certificate /etc/letsencrypt/live/api.seudominio.com.br/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.seudominio.com.br/privkey.pem;
# Proxy para API REST normal
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Proxy para WebSocket
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# Headers de upgrade — OBRIGATÓRIOS para WebSocket
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# Headers padrão
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts para conexões persistentes
proxy_read_timeout 3600s; # 1 hora de timeout de inatividade
proxy_send_timeout 3600s;
}
}Socket.IO com Nginx
Socket.IO tenta WebSocket primeiro e faz fallback para long-polling — configuração específica:
# Socket.IO usa o path /socket.io/ por padrão
# e precisa suportar tanto HTTP (polling) quanto WebSocket
server {
listen 443 ssl http2;
server_name chat.seudominio.com.br;
# Proxy para Socket.IO (websocket + long-polling)
location /socket.io/ {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
# Upgrade para WebSocket
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Sem buffering para long-polling funcionar
proxy_buffering off;
# Timeout longo para WebSocket
proxy_read_timeout 86400s; # 24 horas
# Cache off para SSE/polling
proxy_cache off;
}
location / {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
}
}Load balancing de WebSocket com sticky sessions
WebSocket precisa de sticky sessions no load balancer — a mesma conexão deve ir sempre ao mesmo backend:
# Para WebSocket com múltiplos backends:
# Conexões WebSocket são persistentes — uma vez estabelecida,
# deve continuar no mesmo backend pelo ciclo de vida da conexão
upstream ws_cluster {
# IP hash: garante que o mesmo IP vai ao mesmo servidor
ip_hash;
server 10.0.0.10:3000;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
keepalive 100; # manter conexões abertas entre Nginx e backends
}
server {
listen 443 ssl http2;
server_name ws.seudominio.com.br;
location / {
proxy_pass http://ws_cluster;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 3600s;
}
}Configurar Server-Sent Events (SSE)
SSE é mais simples que WebSocket para streaming unidirecional e precisa de configuração específica:
# SSE usa HTTP regular mas com resposta infinita
# Requer desabilitar buffering e keepalive com timeout longo
server {
location /api/events {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# OBRIGATÓRIO para SSE funcionar:
proxy_set_header Connection ""; # sem Connection: close
proxy_buffering off; # enviar bytes imediatamente
proxy_cache off; # sem cache
# Timeout longo (SSE pode durar horas)
proxy_read_timeout 3600s;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
# Headers CORS para SSE cross-origin:
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Credentials true always;
add_header Cache-Control no-cache always;
add_header X-Accel-Buffering no; # desabilitar buffering do Nginx
}
}Diagnosticar problemas com WebSocket
Como identificar por que conexões WebSocket estão falhando:
# Testar WebSocket via wscat:
npm install -g wscat
wscat -c wss://api.seudominio.com.br/ws/
# Verificar logs do Nginx em tempo real:
sudo tail -f /var/log/nginx/error.log | grep -i "websocket\|upgrade\|101"
# Erros comuns e soluções:
# 1. "502 Bad Gateway" ao conectar
# → Backend não está rodando na porta configurada
# → Verificar: curl http://127.0.0.1:3000/ws/
# 2. Conexão cai após 60 segundos
# → proxy_read_timeout muito curto
# → Aumentar para 3600s e adicionar heartbeat no cliente
# 3. "426 Upgrade Required"
# → Faltam headers Upgrade e Connection no proxy
# → Verificar configuração do location
# 4. "mixed content" no browser
# → Tentando conectar ws:// em página https://
# → Usar wss:// (WebSocket Secure) na aplicação
# Verificar handshake WebSocket com curl:
curl -I -H "Upgrade: websocket" -H "Connection: Upgrade" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZQ==" \
-H "Sec-WebSocket-Version: 13" \
https://api.seudominio.com.br/ws/
# Deve retornar: HTTP/1.1 101 Switching Protocols$ runstack deploy --plan starter
Não quer configurar manualmente?
Não quer configurar manualmente? Implante o VPS em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.