Nginx como proxy inverso para Node.js
Dedicados & VPS
21

Nginx como proxy inverso para Node.js

Node.js puede atender peticiones HTTP por sí solo, pero correrlo directamente en el puerto 80 o 443 en producción no es lo recomendable. La práctica estándar es poner Nginx al frente como proxy inverso. Esto te da varias ventajas que Node por sí solo no resuelve con la misma elegancia.

¿Por qué Nginx delante?

Primero, el tema de privilegios: abrir el puerto 80 requiere permisos de root, y no quieres correr tu app Node como root. Con Nginx delante, tu aplicación escucha tranquila en el puerto 3000 (o el que prefieras) como usuario normal, y Nginx se encarga de atender el 80 y 443.

Segundo, SSL/TLS: Nginx maneja certificados con herramientas como Certbot de manera sencilla. Así liberas a Node de toda la complejidad de la negociación TLS.

Tercero, archivos estáticos: Nginx sirve imágenes, CSS y JS cientos de veces más rápido que Node, porque está escrito en C y optimizado exactamente para eso. Además, Nginx puede comprimir respuestas con gzip, cachear contenido y limitar el rate de peticiones por IP.

Instalación de Nginx

En distribuciones basadas en Debian o Ubuntu:

sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx

Confirma que arrancó abriendo la IP del VPS en tu navegador: deberías ver la página de bienvenida por defecto.

Configuración del server block

Crea un archivo nuevo en /etc/nginx/sites-available/miapp.conf con esta estructura:

server {
    listen 80;
    server_name miapp.com www.miapp.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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;
    }
}

Las directivas proxy_set_header son importantes: sin ellas, tu app Node recibirá la IP de localhost en vez de la IP real del visitante, y no sabrá si la petición original vino por HTTP o HTTPS. Activa el sitio con:

sudo ln -s /etc/nginx/sites-available/miapp.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

El nginx -t verifica la sintaxis antes de recargar. Si falla, te dirá exactamente en qué línea está el problema.

WebSockets

Si tu aplicación usa Socket.IO, WebSockets o cualquier conexión persistente, necesitas agregar dos headers adicionales dentro del bloque location:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Sin estos headers, el proxy corta la conexión porque no reconoce el handshake de upgrade del protocolo WebSocket.

Archivos estáticos directo desde Nginx

Para que Nginx sirva tu carpeta public sin tocar a Node, añade un location específico:

location /static/ {
    alias /var/www/miapp/public/;
    expires 30d;
    access_log off;
}

Con expires 30d le dices al navegador que cachee los archivos por un mes, y access_log off evita llenar los logs con peticiones triviales. Cualquier ruta bajo /static/ pasa por alto a Node, mejorando el rendimiento significativamente en sitios con muchos assets.