Guía de despliegue

Desplegar una aplicación Node.js en un VPS

Desplegar en un VPS Cloud →

Tutorial

Desarrollo

Desplegar una aplicación Node.js en un VPS

Ejecutar una aplicación Node.js en producción exige algo más que un simple `node app.js`: hace falta un gestor de procesos que la reinicie tras un fallo, variables de entorno guardadas fuera del código, un proxy inverso para HTTPS, registros que no llenen el disco y un arranque automático al iniciar el servidor. En un VPS usted controla cada eslabón de esa cadena, a diferencia de una plataforma gestionada que le factura por uso. Esta guía parte de un servidor Ubuntu, vacío o preparado con la plantilla Node.js Stack, y llega hasta las actualizaciones sin cortes.

8 min de lectura7 pasos
Contenido· ¿Por qué desplegar Node.js en un VPS en lugar de en una plataforma gestionada?1/8
  1. 01¿Por qué desplegar Node.js en un VPS en lugar de en una plataforma gestionada?
  2. 02Lo que gana con un VPS para Node.js
  3. 03Requisitos previos
  4. 04Partir de la plantilla Node.js Stack
  5. 05Desplegar una aplicación Node.js en producción
  6. 06Centralizar la configuración en ecosystem.config.js
  7. 07Registros: leerlos y después rotarlos
  8. 08La documentación oficial

¿Por qué desplegar Node.js en un VPS en lugar de en una plataforma gestionada?

Las plataformas serverless y PaaS resultan cómodas al principio, pero su coste crece con el tráfico e imponen restricciones (timeouts, cold starts, límites de conexiones WebSocket). Un VPS le ofrece un proceso Node.js persistente, conexiones largas (WebSocket, SSE) sin límites artificiales, recursos dedicados y un coste fijo y previsible. Usted decide la versión de Node, el gestor de procesos, el proxy inverso y la estrategia de actualización, sin depender de las convenciones de un proveedor.

El modelo asíncrono y no bloqueante de Node.js permite que un único proceso mantenga un gran número de conexiones simultáneas: por eso es un buen candidato para API REST, funciones en tiempo real y microservicios, siempre que ese proceso siga vivo. Es justo lo que rechazan la mayoría de los alojamientos compartidos, que prohíben los procesos persistentes o los WebSocket. En un VPS, sus dependencias npm, sus variables de entorno y su configuración de PM2 no se comparten con ninguna otra cuenta.

Lo que gana con un VPS para Node.js

  • Proceso Node.js persistente, ideal para WebSocket, SSE y tareas largas sin cold start
  • Reinicio automático tras un fallo y al reiniciar el servidor gracias a PM2
  • Modo cluster para aprovechar todos los núcleos de CPU del VPS sin cambiar su código
  • Proxy inverso Nginx delante de Node para HTTPS, compresión y archivos estáticos
  • Workers de colas (BullMQ, Agenda) y tareas programadas que se ejecutan junto a la API, en la misma máquina
  • Varias aplicaciones en un solo VPS, cada una en su puerto interno (3000, 3001…) y su subdominio detrás de Nginx
  • Renderizado en servidor de frameworks como Nuxt o Next.js, servidos por la misma base de Node.js y PM2
  • Coste fijo y previsible, sin facturación por petición ni sorpresas al escalar
  • Control total de la versión de Node.js y de las dependencias del sistema

Requisitos previos

Una aplicación Node.js estándar (API Express, Nest, Fastify) funciona con holgura en un VPS de 1 a 2 vCPU y de 1 a 2 GB de RAM; prevea más RAM si compila un front pesado durante el build o ejecuta workers. Apunte a 2 vCPU y 2 GB en cuanto la API comparta la máquina con un renderizado SSR o una base de datos PostgreSQL.

Elija una línea LTS que siga mantenida: Node.js 20 ya no recibe correcciones desde el 30 de abril de 2026, Node.js 24 pasó a mantenimiento el 20 de octubre de 2026 y Node.js 26 es la LTS activa desde el 28 de octubre de 2026. Instálela mediante nvm o el repositorio de NodeSource para fijarla, junto con PM2 como gestor de procesos y Nginx como proxy inverso. Necesita un dominio que apunte a la IP del VPS y los puertos 80/443 abiertos.

Partir de la plantilla Node.js Stack

La plantilla Node.js Stack del Marketplace de ServOrbit prepara un VPS Ubuntu 24.04 con Node.js en la línea LTS actual del repositorio de NodeSource, npm, PM2 instalado de forma global, Nginx y PostgreSQL. Le ahorra el primer paso de la lista siguiente; el resto de la guía se aplica tal cual.

No es una aplicación con pantalla de inicio de sesión, sino un entorno de ejecución: se accede por SSH (ssh root@<ip-del-vps>) para subir el código. En el primer acceso, Nginx sirve su página de bienvenida por defecto en el puerto 80, porque aún no hay ningún virtual host escrito para su dominio, y Certbot no está instalado: los pasos de Nginx y HTTPS siguen pendientes. PostgreSQL solo escucha en local y autentica al usuario del sistema postgres con el método peer: sudo -u postgres psql abre la consola sin contraseña.

Desplegar una aplicación Node.js en producción

  1. Preparar el VPS e instalar Node.js

    En un VPS Ubuntu 24.04, actualice el sistema e instale una versión LTS de Node mediante nvm (nvm install --lts) o el repositorio de NodeSource. Compruebe con node -v y npm -v. Cree un usuario no root dedicado a la aplicación en lugar de ejecutarlo todo como root: ese usuario será el propietario del código, del archivo .env y de los procesos de PM2. Con la plantilla Node.js Stack, Node.js, npm y PM2 ya están instalados: solo queda crear el usuario.

  2. Obtener el código y hacer el build

    Clone su repositorio en el VPS, instale las dependencias de producción (npm ci --omit=dev) y lance el build si hace falta (npm run build).

    Guarde las variables sensibles en un archivo .env no versionado, legible solo por el usuario de la aplicación (chmod 600 .env). No necesita ninguna librería para leerlo: desde Node.js 20.6, la opción --env-file carga ese archivo en process.env al arrancar.

  3. Preparar la base de datos PostgreSQL

    Si la aplicación necesita una base de datos, cree un rol y una base dedicados en lugar de trabajar con el superusuario:

    sudo -u postgres createuser --pwprompt monapp
    sudo -u postgres createdb --owner=monapp monapp

    Después indique DATABASE_URL=postgres://monapp:<contraseña>@127.0.0.1:5432/monapp en el .env. Como PostgreSQL solo escucha en local, no hay que abrir ningún puerto de base de datos en el cortafuegos.

  4. Lanzar la aplicación con PM2

    Instale PM2 de forma global (npm install -g pm2, ya hecho en la plantilla) y arranque la aplicación desde la carpeta del proyecto, pidiendo a Node que cargue el .env:

    pm2 start app.js --name monapp -i max --node-args="--env-file=.env"

    El flag -i max activa el modo cluster en todos los núcleos. PM2 reinicia automáticamente el proceso si falla.

  5. Activar el arranque automático al iniciar

    Genere el script de systemd con pm2 startup, ejecutado por el usuario de la aplicación, lance con sudo el comando que se muestra y después fije el estado actual con pm2 save. En el próximo reinicio del VPS, su aplicación se relanzará automáticamente, sin intervención.

  6. Configurar Nginx como proxy inverso

    Instale Nginx si aún no está presente y cree /etc/nginx/sites-available/monapp, un virtual host que redirige al puerto local de Node. Las cabeceras Upgrade y Connection sirven para los WebSocket, y X-Forwarded-Proto indica a la aplicación que el cliente está en HTTPS:

    server {
        listen 80;
        server_name yourdomain.com;
    
        location / {
            proxy_pass http://127.0.0.1:3000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }

    Active el sitio, retire la página por defecto, pruebe la configuración y recargue:

    ln -s /etc/nginx/sites-available/monapp /etc/nginx/sites-enabled/
    rm /etc/nginx/sites-enabled/default
    nginx -t && systemctl reload nginx
  7. Proteger con HTTPS mediante Let's Encrypt

    Instale Certbot y su plugin para Nginx y solicite el certificado:

    apt install certbot python3-certbot-nginx
    certbot --nginx -d yourdomain.com

    Certbot obtiene el certificado, configura la redirección HTTP→HTTPS y programa la renovación automática. Su aplicación Node ya se sirve en HTTPS.

Centralizar la configuración en ecosystem.config.js

En cuanto el VPS aloja más de una aplicación, o una API va acompañada de un worker, las opciones pasadas por línea de comandos se vuelven difíciles de seguir. PM2 lee un archivo ecosystem.config.js que describe cada proceso: script, carpeta, número de instancias, límite de memoria y variables no sensibles.

module.exports = {
  apps: [
    {
      name: 'api',
      cwd: '/home/monapp/app',
      script: 'app.js',
      instances: 'max',
      exec_mode: 'cluster',
      node_args: '--env-file=.env',
      max_memory_restart: '500M',
      env: { NODE_ENV: 'production', PORT: 3000 }
    },
    {
      name: 'worker',
      cwd: '/home/monapp/app',
      script: 'worker.js',
      node_args: '--env-file=.env'
    }
  ]
}

pm2 start ecosystem.config.js arranca el conjunto, pm2 reload ecosystem.config.js lo actualiza y la opción --only api apunta a una sola aplicación. Aquí la API funciona en modo cluster en todos los núcleos y el worker en un único proceso. Versione este archivo junto con el código; los secretos, en cambio, se quedan en el .env, fuera del repositorio.

Registros: leerlos y después rotarlos

PM2 captura la salida estándar y la salida de errores de cada proceso en ~/.pm2/logs/, con un archivo -out.log y otro -error.log por aplicación. pm2 logs monapp los sigue en directo y pm2 logs monapp --lines 100 muestra las últimas líneas.

Sin rotación, estos archivos crecen hasta llenar el disco. El módulo pm2-logrotate se encarga de ello; por defecto rota un archivo al superar los 10 MB y conserva 30, umbrales que se ajustan con facilidad:

pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7

En el lado del proxy, un error 502 aparece en /var/log/nginx/error.log: casi siempre significa que el proceso Node.js está detenido o escucha en un puerto distinto del indicado en proxy_pass.

Para despliegues sin interrupción, combine el modo cluster de PM2 con pm2 reload monapp en lugar de restart: PM2 reinicia los workers uno a uno y mantiene siempre al menos una instancia disponible durante la actualización. Vigile después la memoria con pm2 monit y fije un límite de reinicio automático (--max-memory-restart 500M) para prevenir las fugas de memoria en producción.

La documentación oficial

Para las opciones propias de cada herramienta y los cambios de versión, consulte la documentación oficial de Node.js, el calendario de versiones LTS de Node.js y la documentación de PM2. Esta guía cubre la puesta en producción en un VPS; la documentación del editor sigue siendo la referencia para los ajustes finos.

Ponga su aplicación Node.js en producción en un VPS Cloud

Despliegue un VPS Cloud ServOrbit con la plantilla Desarrollo: Node.js, PM2 y Nginx preconfigurados para pasar su aplicación a producción en HTTPS.