Cómo desplegar una aplicación Node.js en una VPS con Nginx
Desarrollar una aplicación Node.js en nuestro ordenador es relativamente sencillo. El siguiente paso es publicarla en Internet para que pueda ser utilizada desde un dominio y permanezca disponible las 24 horas.
En esta guía aprenderás a desplegar una aplicación Node.js en una VPS con Ubuntu o Debian, mantenerla funcionando mediante PM2 y utilizar Nginx como reverse proxy.
Al finalizar tendremos una arquitectura similar a esta:
Internet
│
▼
https://app.midominio.com
│
▼
Nginx :443
│
▼
127.0.0.1:3000
│
▼
Aplicación Node.js
│
▼
PM2
Nuestra aplicación Node.js no estará expuesta directamente a Internet. Nginx recibirá las conexiones HTTP/HTTPS y las enviará internamente hacia Node.js.
También configuraremos un certificado SSL gratuito para acceder a nuestra aplicación mediante HTTPS.
¿Qué necesitamos?
Para seguir esta guía necesitaremos:
- Una VPS con Ubuntu o Debian.
- Acceso mediante SSH.
- Usuario con permisos
sudo. - Una aplicación Node.js.
- Un dominio o subdominio.
- Acceso a la configuración DNS del dominio.
Para las pruebas utilizaremos:
app.midominio.com
y nuestra aplicación escuchará internamente en:
127.0.0.1:3000
Debes sustituir app.midominio.com por tu propio dominio.
1. Conectarnos a la VPS mediante SSH
Desde Linux, macOS o Windows podemos conectarnos utilizando:
ssh usuario@IP_DEL_SERVIDOR
Por ejemplo:
ssh root@203.0.113.10
O si utilizamos un usuario diferente:
ssh usuario@203.0.113.10
Una vez dentro podemos comenzar a preparar el servidor.
2. Actualizar Ubuntu o Debian
Antes de instalar los paquetes actualizamos la información de los repositorios:
sudo apt update
También podemos actualizar los paquetes instalados:
sudo apt upgrade -y
3. Instalar las herramientas necesarias
Instalamos curl, Git y algunas utilidades básicas:
sudo apt install curl git ca-certificates -y
Comprobamos Git:
git --version
4. Instalar Node.js
Para un servidor en producción es recomendable utilizar una versión LTS de Node.js.
Vamos a utilizar los paquetes distribuidos mediante NodeSource para Ubuntu y Debian.
Descargamos el instalador de la rama LTS:
curl -fsSL https://deb.nodesource.com/setup_lts.x -o nodesource_setup.sh
Ejecutamos el script:
sudo -E bash nodesource_setup.sh
Ahora instalamos Node.js:
sudo apt install nodejs -y
Con este paquete también tendremos disponible npm.
5. Comprobar Node.js y npm
Consultamos la versión instalada:
node -v
Y comprobamos npm:
npm -v
Si ambos comandos muestran una versión, Node.js está correctamente instalado.
Para aplicaciones en producción conviene utilizar versiones LTS en lugar de versiones experimentales o que hayan alcanzado su fin de soporte.
6. Subir nuestra aplicación Node.js
Existen diferentes formas de subir una aplicación a nuestra VPS.
Podemos utilizar:
- Git.
- GitHub.
- GitLab.
- SFTP.
- SCP.
- rsync.
- Un sistema de despliegue automatizado.
En este ejemplo utilizaremos Git.
Creamos el directorio donde almacenaremos nuestras aplicaciones:
sudo mkdir -p /var/www
Asignamos el directorio a nuestro usuario:
sudo chown -R $USER:$USER /var/www
Entramos:
cd /var/www
Ahora clonamos nuestro proyecto:
git clone https://github.com/usuario/mi-aplicacion.git
Entramos en el proyecto:
cd mi-aplicacion
7. Instalar las dependencias
Si nuestro proyecto contiene:
package-lock.json
es recomendable utilizar:
npm ci
npm ci instala exactamente las versiones definidas en el archivo de bloqueo.
Si nuestro proyecto no dispone de package-lock.json, podemos ejecutar:
npm install
8. Crear una aplicación Node.js de prueba
Si todavía no tienes una aplicación preparada, podemos crear una sencilla para comprobar todo el despliegue.
Creamos un directorio:
mkdir -p /var/www/node-demo
Entramos:
cd /var/www/node-demo
Inicializamos el proyecto:
npm init -y
Instalamos Express:
npm install express
Creamos:
nano app.js
Y añadimos:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
const HOST = '127.0.0.1';
app.get('/', (req, res) => {
res.send(`
<h1>¡Node.js está funcionando!</h1>
<p>Aplicación desplegada correctamente en nuestra VPS.</p>
`);
});
app.listen(PORT, HOST, () => {
console.log(`Aplicación ejecutándose en http://${HOST}:${PORT}`);
});
Guardamos el archivo.
Ahora podemos ejecutarlo:
node app.js
Deberíamos obtener:
Aplicación ejecutándose en http://127.0.0.1:3000
9. Comprobar la aplicación
Sin cerrar la aplicación podemos abrir otra conexión SSH y ejecutar:
curl http://127.0.0.1:3000
Deberíamos recibir el HTML de nuestra aplicación.
También podemos comprobar qué proceso utiliza el puerto:
sudo ss -tulpn | grep :3000
Lo ideal en esta configuración es encontrar:
127.0.0.1:3000
en lugar de:
0.0.0.0:3000
Esto significa que nuestra aplicación solamente acepta conexiones desde el propio servidor.
Nginx será quien posteriormente se encargue de aceptar conexiones públicas.
10. ¿Por qué no ejecutar simplemente node app.js?
Si iniciamos nuestra aplicación mediante:
node app.js
funcionará mientras nuestra terminal permanezca abierta.
Pero si:
- Cerramos SSH.
- La aplicación falla.
- El proceso termina.
- Reiniciamos la VPS.
nuestra aplicación dejará de estar disponible.
Para evitarlo utilizaremos un gestor de procesos.
11. Instalar PM2
PM2 es un administrador de procesos especialmente popular para aplicaciones Node.js.
Lo instalamos globalmente mediante npm:
sudo npm install -g pm2
Comprobamos la instalación:
pm2 --version
12. Ejecutar nuestra aplicación con PM2
Si nuestra aplicación se inicia mediante:
node app.js
podemos utilizar:
pm2 start app.js --name mi-app
PM2 iniciará Node.js en segundo plano.
Consultamos las aplicaciones:
pm2 list
Deberíamos encontrar:
mi-app
con estado:
online
13. Ejecutar un proyecto mediante npm
Muchas aplicaciones tienen definido un comando:
npm start
En ese caso podemos ejecutar:
pm2 start npm --name mi-app -- start
Por ejemplo, si nuestro package.json contiene:
{
"scripts": {
"start": "node app.js"
}
}
PM2 ejecutará automáticamente:
npm start
14. Consultar los logs de la aplicación
Podemos ver los logs mediante:
pm2 logs mi-app
Para mostrar únicamente las últimas líneas:
pm2 logs mi-app --lines 100
También podemos consultar todos los procesos:
pm2 list
Y obtener información detallada:
pm2 show mi-app
15. Reiniciar nuestra aplicación
Después de realizar cambios:
pm2 restart mi-app
Para detenerla:
pm2 stop mi-app
Y volver a iniciarla:
pm2 start mi-app
También podemos eliminarla completamente de PM2:
pm2 delete mi-app
16. Hacer que Node.js arranque después de reiniciar la VPS
Ahora tenemos un problema.
Si reiniciamos completamente el servidor, necesitamos que PM2 vuelva a iniciar nuestras aplicaciones.
Primero ejecutamos:
pm2 startup
PM2 detectará automáticamente systemd y mostrará un comando que debemos ejecutar con sudo.
Será parecido a:
sudo env PATH=$PATH:... pm2 startup systemd -u usuario --hp /home/usuario
Debemos copiar y ejecutar exactamente el comando que PM2 muestre en nuestro servidor.
Después guardamos la lista actual de procesos:
pm2 save
Ahora PM2 podrá recuperar nuestras aplicaciones después de reiniciar el servidor.
Podemos comprobarlo reiniciando:
sudo reboot
Después de volver a conectarnos:
pm2 list
Nuestra aplicación debería aparecer nuevamente como:
online
17. Instalar Nginx
Ahora vamos a colocar Nginx delante de nuestra aplicación.
Instalamos:
sudo apt install nginx -y
Comprobamos su estado:
sudo systemctl status nginx
Debería aparecer:
active (running)
También podemos hacer que se inicie automáticamente:
sudo systemctl enable nginx
18. Configurar el DNS del dominio
Antes de configurar HTTPS necesitamos que nuestro dominio apunte hacia la VPS.
En nuestro proveedor DNS creamos un registro:
Tipo: A
Nombre: app
Destino: IP_DE_LA_VPS
Por ejemplo:
app.midominio.com → 203.0.113.10
Podemos comprobar la resolución utilizando:
ping app.midominio.com
O:
dig app.midominio.com
También podemos utilizar:
nslookup app.midominio.com
La dirección devuelta debe coincidir con la IP pública de nuestra VPS.
19. Configurar Nginx como reverse proxy
Ahora creamos una configuración específica para nuestra aplicación:
sudo nano /etc/nginx/sites-available/mi-app
Añadimos:
server {
listen 80;
listen [::]:80;
server_name app.midominio.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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Debemos sustituir:
app.midominio.com
por nuestro dominio real.
Y:
127.0.0.1:3000
por el puerto utilizado por nuestra aplicación.
20. ¿Qué hace proxy_pass?
La parte más importante de nuestra configuración es:
proxy_pass http://127.0.0.1:3000;
Cuando alguien accede a:
https://app.midominio.com
Nginx recibe la solicitud.
Después la envía internamente hacia:
http://127.0.0.1:3000
Nuestra aplicación Node.js procesa la petición y devuelve la respuesta a Nginx.
Finalmente Nginx envía esa respuesta al usuario.
De esta manera el visitante nunca necesita acceder directamente al puerto 3000.
21. Habilitar nuestra configuración de Nginx
Creamos un enlace simbólico:
sudo ln -s /etc/nginx/sites-available/mi-app /etc/nginx/sites-enabled/
Antes de aplicar los cambios comprobamos siempre la sintaxis:
sudo nginx -t
Si todo está correcto veremos algo parecido a:
syntax is ok
test is successful
Aplicamos los cambios:
sudo systemctl reload nginx
Ahora podemos acceder a:
http://app.midominio.com
Nuestra aplicación Node.js debería aparecer en el navegador.
22. ¿Por qué utilizar Nginx delante de Node.js?
Podríamos hacer que Node.js escuchara directamente mediante:
0.0.0.0:3000
y acceder utilizando:
http://IP:3000
Pero para un entorno de producción normalmente resulta mucho más práctico colocar un reverse proxy delante.
Nginx puede encargarse de:
- HTTP.
- HTTPS.
- Certificados SSL.
- Dominios y subdominios.
- Redirecciones.
- Compresión.
- Caché.
- Cabeceras.
- Rate limiting.
- Archivos estáticos.
- Múltiples aplicaciones dentro de una misma VPS.
Nuestra aplicación Node.js puede mantenerse escuchando únicamente de forma local.
23. Comprobar que el puerto 3000 no está expuesto
Ejecutamos:
sudo ss -tulpn | grep :3000
Si nuestra aplicación está configurada como en el ejemplo deberíamos ver:
127.0.0.1:3000
Esto significa que únicamente el propio servidor puede conectarse directamente al puerto.
Desde Internet los usuarios accederán utilizando:
80
443
a través de Nginx.
24. Configurar el firewall
Si nuestro servidor utiliza UFW podemos permitir SSH:
sudo ufw allow OpenSSH
Y permitir Nginx:
sudo ufw allow 'Nginx Full'
Consultamos las reglas:
sudo ufw status
Los puertos web necesarios serán:
80/TCP
443/TCP
No necesitamos abrir:
3000/TCP
porque nuestra aplicación solamente debe ser accesible internamente mediante Nginx.
Antes de activar un firewall mediante SSH, comprueba siempre que el puerto SSH esté permitido para evitar perder el acceso al servidor.
25. Añadir HTTPS a nuestra aplicación
Una vez que:
http://app.midominio.com
funcione correctamente podemos configurar HTTPS.
Necesitaremos un certificado SSL.
Una opción muy utilizada es Let's Encrypt mediante Certbot.
En Ubuntu y Debian podemos instalar los paquetes disponibles para Nginx:
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
Después solicitamos el certificado:
sudo certbot --nginx -d app.midominio.com
Certbot comprobará el dominio y podrá modificar nuestra configuración de Nginx para habilitar HTTPS.
26. Comprobar HTTPS
Después de terminar podemos abrir:
https://app.midominio.com
Nuestra aplicación debería cargarse mediante una conexión HTTPS.
También podemos comprobar Nginx:
sudo nginx -t
Y recargarlo:
sudo systemctl reload nginx
27. Comprobar la renovación automática del certificado
Los certificados de Let's Encrypt deben renovarse periódicamente.
Podemos comprobar que el proceso de renovación funciona mediante:
sudo certbot renew --dry-run
Si la prueba termina correctamente, nuestro sistema está preparado para renovar el certificado cuando sea necesario.
28. Aplicaciones Node.js con WebSockets
Algunas aplicaciones Node.js utilizan WebSockets.
Por ejemplo:
- Chats.
- Socket.IO.
- Notificaciones en tiempo real.
- Dashboards.
- Juegos.
- Sistemas de monitorización.
En nuestro reverse proxy hemos incluido:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
Estas cabeceras permiten que Nginx gestione correctamente el cambio de protocolo necesario para determinadas conexiones WebSocket.
Una configuración típica sería:
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
29. Configurar variables de entorno
Las aplicaciones reales suelen necesitar información como:
DATABASE_URL
JWT_SECRET
API_KEY
PORT
NODE_ENV
Nunca debemos almacenar contraseñas o secretos directamente en un repositorio Git público.
Podemos utilizar variables de entorno o un archivo:
.env
Por ejemplo:
NODE_ENV=production
PORT=3000
DATABASE_URL=mysql://usuario:password@127.0.0.1/database
Es muy importante añadir .env al:
.gitignore
Por ejemplo:
node_modules/
.env
para evitar subir nuestras credenciales accidentalmente al repositorio.
30. Configurar NODE_ENV en producción
Muchas aplicaciones Node.js modifican su comportamiento dependiendo del entorno.
Podemos definir:
NODE_ENV=production
Si utilizamos PM2 podemos crear un archivo:
nano ecosystem.config.js
Por ejemplo:
module.exports = {
apps: [
{
name: 'mi-app',
script: './app.js',
env: {
NODE_ENV: 'production',
PORT: 3000
}
}
]
};
Ahora podemos iniciar nuestra aplicación:
pm2 start ecosystem.config.js
Guardamos:
pm2 save
31. Actualizar nuestra aplicación desde Git
Una vez que la aplicación está publicada seguramente necesitaremos desplegar cambios.
Entramos en el proyecto:
cd /var/www/mi-aplicacion
Descargamos los cambios:
git pull
Instalamos las dependencias exactamente como están definidas:
npm ci
Y reiniciamos:
pm2 restart mi-app
Si hemos modificado variables de entorno:
pm2 restart mi-app --update-env
Podemos comprobar:
pm2 list
Y revisar los logs:
pm2 logs mi-app
32. Flujo habitual para actualizar una aplicación Node.js
En muchos proyectos el proceso será simplemente:
cd /var/www/mi-aplicacion
git pull
npm ci
pm2 restart mi-app --update-env
Si nuestra aplicación necesita compilarse también tendremos que ejecutar:
npm run build
antes de reiniciar.
Por ejemplo:
git pull
npm ci
npm run build
pm2 restart mi-app --update-env
El procedimiento exacto dependerá de nuestro proyecto.
33. Ver el consumo de nuestra aplicación
PM2 incluye una interfaz de monitorización en terminal:
pm2 monit
También podemos consultar:
pm2 list
Ahí encontraremos información como:
- Estado.
- CPU.
- Memoria.
- Tiempo activo.
- Reinicios.
- PID.
También podemos utilizar herramientas del sistema:
top
o:
htop
si está instalado.
34. Ver logs de Nginx
Si nuestra aplicación funciona mediante:
127.0.0.1:3000
pero no mediante el dominio, deberíamos revisar Nginx.
Logs de acceso:
sudo tail -f /var/log/nginx/access.log
Logs de errores:
sudo tail -f /var/log/nginx/error.log
También podemos comprobar la configuración:
sudo nginx -t
35. Error 502 Bad Gateway
Uno de los problemas más habituales al desplegar Node.js detrás de Nginx es:
502 Bad Gateway
Normalmente significa que Nginx no puede conectarse con nuestra aplicación.
Comprobamos PM2:
pm2 list
Si la aplicación aparece detenida:
pm2 restart mi-app
Revisamos los logs:
pm2 logs mi-app
Después comprobamos directamente:
curl http://127.0.0.1:3000
Si esto falla, el problema probablemente está en Node.js y no en Nginx.
36. Comprobar que Node.js utiliza el puerto correcto
Ejecutamos:
sudo ss -tulpn | grep node
O:
sudo ss -tulpn | grep :3000
Si nuestra aplicación escucha en otro puerto debemos modificar:
proxy_pass http://127.0.0.1:3000;
para que coincida.
Por ejemplo, si Node.js utiliza:
4000
configuraremos:
proxy_pass http://127.0.0.1:4000;
Después:
sudo nginx -t
sudo systemctl reload nginx
37. Error EADDRINUSE
Podemos encontrarnos con un error parecido a:
EADDRINUSE: address already in use
Esto significa que otro proceso ya está utilizando el puerto.
Comprobamos:
sudo ss -tulpn | grep :3000
También podemos utilizar:
sudo lsof -i :3000
Si ya existe nuestra aplicación ejecutándose mediante PM2, no debemos iniciar otra copia manualmente con:
node app.js
38. La aplicación funciona por IP pero no por dominio
Primero comprobamos el DNS:
dig app.midominio.com
La IP debe coincidir con nuestra VPS.
Después comprobamos Nginx:
sudo nginx -t
Revisamos:
server_name app.midominio.com;
Y recargamos:
sudo systemctl reload nginx
También debemos recordar que los cambios DNS pueden necesitar tiempo para propagarse dependiendo del TTL y del proveedor utilizado.
39. La aplicación funciona pero PM2 no vuelve después de reiniciar
Comprobamos:
pm2 list
Después ejecutamos:
pm2 startup
Ejecutamos el comando que PM2 nos indique.
Finalmente:
pm2 save
Podemos comprobar el servicio generado mediante:
systemctl list-units | grep pm2
40. Reiniciar Nginx correctamente
Cuando cambiamos una configuración no conviene reiniciar Nginx inmediatamente sin comprobar primero la sintaxis.
Siempre deberíamos ejecutar:
sudo nginx -t
Si todo es correcto:
sudo systemctl reload nginx
reload permite cargar la nueva configuración sin realizar un reinicio completo innecesario del servicio.
41. Estructura final de nuestro servidor
Después de completar la guía podemos tener algo parecido a:
/var/www/
└── mi-aplicacion/
├── app.js
├── package.json
├── package-lock.json
├── node_modules/
└── .env
Nuestra infraestructura:
Usuario
│
│ HTTPS
▼
Nginx
│
│ HTTP interno
▼
127.0.0.1:3000
│
▼
Node.js
│
▼
PM2
Y nuestros servicios principales:
Nginx → puerto 80/443 público
Node.js → puerto 3000 local
PM2 → mantiene Node.js funcionando
Certbot → certificado SSL
42. Comandos útiles para administrar nuestra aplicación
Estado de PM2
pm2 list
Logs
pm2 logs mi-app
Reiniciar aplicación
pm2 restart mi-app
Detener aplicación
pm2 stop mi-app
Monitorizar recursos
pm2 monit
Guardar procesos
pm2 save
Comprobar Node.js
node -v
Comprobar Nginx
sudo nginx -t
Recargar Nginx
sudo systemctl reload nginx
Comprobar el backend
curl http://127.0.0.1:3000
Consultar puertos
sudo ss -tulpn
43. ¿Cuánta RAM necesita una aplicación Node.js?
No existe una cantidad universal.
Los recursos dependerán de:
- Número de usuarios.
- Tipo de aplicación.
- Dependencias.
- Uso de bases de datos.
- Procesos en segundo plano.
- Consumo de memoria.
- Número de aplicaciones alojadas.
- Compilaciones realizadas en el servidor.
Para aplicaciones pequeñas una VPS básica puede ser suficiente.
Aplicaciones con bases de datos, procesamiento intensivo, muchos usuarios o múltiples servicios necesitarán más CPU y RAM.
Podemos comprobar el consumo real mediante:
pm2 monit
y:
free -h
44. Desplegar varias aplicaciones Node.js en la misma VPS
Una ventaja de utilizar Nginx es que podemos alojar varias aplicaciones en un mismo servidor.
Por ejemplo:
api.midominio.com → 127.0.0.1:3000
panel.midominio.com → 127.0.0.1:3001
chat.midominio.com → 127.0.0.1:3002
Podemos crear diferentes bloques server de Nginx.
Por ejemplo:
server {
listen 80;
server_name api.midominio.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
Y otro:
server {
listen 80;
server_name panel.midominio.com;
location / {
proxy_pass http://127.0.0.1:3001;
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;
}
}
De esta forma una sola IP pública puede servir diferentes aplicaciones utilizando distintos dominios.
45. Node.js + Nginx frente a Docker
También podemos desplegar aplicaciones Node.js utilizando Docker.
Ambas opciones son válidas.
Una instalación tradicional:
Node.js
PM2
Nginx
es sencilla de entender y administrar para una única aplicación.
Con Docker podemos encapsular:
Aplicación
Node.js
Dependencias
Configuración
dentro de contenedores, algo especialmente útil cuando gestionamos diferentes proyectos o queremos despliegues reproducibles.
La elección dependerá de la arquitectura y necesidades del proyecto.
Desplegar Node.js en una VPS
Para publicar una aplicación Node.js necesitamos un servidor donde tengamos control sobre Node.js, Nginx y los procesos del sistema.
Una VPS nos permite disponer de:
- Acceso root.
- Dirección IP pública.
- Node.js.
- npm.
- Nginx.
- PM2.
- Bases de datos.
- Docker.
- Certificados SSL.
- Dominios y subdominios.
Si necesitas desplegar tu aplicación Node.js, puedes utilizar una VPS de ColdHosting con Ubuntu o Debian, conectarte mediante SSH y seguir esta guía desde el primer paso.
Conclusión
Desplegar una aplicación Node.js en una VPS requiere algo más que ejecutar:
node app.js
En un entorno de producción necesitamos asegurarnos de que nuestra aplicación permanezca funcionando, sea accesible mediante un dominio y utilice HTTPS.
En esta guía hemos configurado:
Node.js
+
PM2
+
Nginx
+
Let's Encrypt
=
Aplicación lista para producción
PM2 mantiene nuestra aplicación activa y permite recuperarla después de reiniciar el servidor.
Nginx funciona como reverse proxy y recibe las conexiones públicas mediante los puertos 80 y 443.
Nuestra aplicación Node.js permanece escuchando únicamente en:
127.0.0.1:3000
evitando exponer directamente el puerto de la aplicación a Internet.
Finalmente, mediante Certbot y Let's Encrypt podemos servir nuestra aplicación utilizando:
https://app.midominio.com
Antes de aplicar cualquier modificación en Nginx recuerda ejecutar siempre:
sudo nginx -t
Y si realizas cambios en tu aplicación:
pm2 restart mi-app
Con esta arquitectura ya tenemos una base sólida para desplegar aplicaciones Node.js en una VPS Ubuntu o Debian.



