¿Un Node.js para todo? Nginx y Node: La estrategia de un dev chileno

Cuando integras Nginx con Node.js, es tentador pensar en un solo servidor Node para todas tus apps. Yo te digo por qué esa solución te dará problemas y cuál es la alternativa más robusta.

Nginx y Node.js: No mezcles peras con manzanas

Cuando recién te metes a esto de Nginx con Node.js, es común que la primera idea sea montar un solo servidor Node que atienda todos tus dominios y subdominios. La lógica te dice: “si Node puede levantar un servidor HTTP, que él se encargue de todo”. Yo te digo, altiro, que esa es una receta para el dolor de cabeza.

La verdad es que no tiene sentido. Cada uno tiene su pega. Nginx es un campeón para servir contenido estático, balancear cargas y, sobre todo, actuar como un proxy inverso. Node.js, por su parte, es brillante para la lógica de negocio y las operaciones de entrada/salida no bloqueantes.

La forma correcta: Nginx como tu portero

En mi experiencia, la forma más limpia y robusta de hacer esto es que Nginx actúe como un proxy inverso. Su trabajo es escuchar las peticiones en los puertos 80 y 443, y luego redirigirlas a tus procesos Node.js. Esto significa que cada aplicación Node corre de forma independiente, en su propio puerto.

Así, si tienes dominio1.cl y dominio2.cl, Nginx recibe ambas peticiones. La de dominio1.cl la manda a tu app Node en el puerto 3000, y la de dominio2.cl a la app Node en el puerto 4000. Son procesos separados y, de hecho, se pueden escalar de forma independiente.

Configurando Nginx para una app Node

Aquí tienes una configuración básica de Nginx para un dominio que apunta a una aplicación Node.js corriendo en localhost:3000. Esto iría en un archivo como /etc/nginx/sites-available/tu-dominio.cl y luego lo activas con un symlink a sites-enabled.

server {
    listen 80;
    listen [::]:80;
    server_name tu-dominio.cl www.tu-dominio.cl;
    access_log /var/log/nginx/tu-dominio.access.log;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://127.0.0.1:3000/; # ¡Aquí tu app Node!
        proxy_redirect off;

        # Ojo si necesitas WebSockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Con esta configuración, Nginx se encarga de las cabeceras HTTP y el enrutamiento. Tu aplicación Node.js solo necesita escuchar en el puerto especificado (en este caso, 3000) y manejar la lógica de tu aplicación.

No te olvides del proceso de Node

Un error común es simplemente ejecutar node app.js. Eso no es robusto. Si la aplicación cae o el servidor se reinicia, tu app Node se muere. Necesitas un gestor de procesos como PM2 o configurar un servicio con systemd. Esto asegura que tu app esté siempre corriendo y se reinicie automáticamente si algo sale mal.

Si partiera de cero...

Si tuviera que empezar de cero hoy, haría exactamente lo que te acabo de describir. Desde el primer día, Nginx sería mi proxy para todas las apps, cada una corriendo en su propio proceso Node.js aislado, gestionado por PM2 o systemd. Me habría ahorrado varios dolores de cabeza intentando que un solo Node hiciera la pega de Nginx. La especialización, en este caso, es tu mejor aliada.

Jorge RequenaDeveloper full-stack · Chile