Cómo Configurar una Aplicación Node.js para Producción en Rocky Linux 9

Introducción

Node.js es un entorno de tiempo de ejecución de JavaScript de código abierto para construir aplicaciones del lado del servidor y de redes. La plataforma se ejecuta en Linux, macOS, FreeBSD y Windows. Aunque puedes ejecutar aplicaciones Node.js en la línea de comandos, este tutorial se centrará en ejecutarlas como un servicio. Esto significa que se reiniciarán al reiniciar o fallar y son seguras para su uso en un entorno de producción.

En este tutorial, configurarás un entorno Node.js listo para producción en un único servidor Rocky Linux 9. Este servidor ejecutará una aplicación Node.js gestionada por PM2 y proporcionará a los usuarios un acceso seguro a la aplicación a través de un proxy inverso Nginx. El servidor Nginx ofrecerá HTTPS utilizando un certificado gratuito proporcionado por Let’s Encrypt.

Prerrequisitos

Esta guía asume que tienes lo siguiente:

Cuando hayas completado los requisitos previos, tendrás un servidor sirviendo la página de inicio predeterminada de tu dominio en https://example.com/.

Paso 1 — Creando una Aplicación Node.js

Escribamos una aplicación Hola Mundo que devuelva “Hola Mundo” a cualquier solicitud HTTP. Esta aplicación de ejemplo te ayudará a comenzar con Node.js. Puedes reemplazarla con tu propia aplicación, solo asegúrate de modificar tu aplicación para escuchar en las direcciones IP y puertos apropiados.

El editor de texto predeterminado que viene con Rocky Linux 9 es vi. vi es un editor de texto extremadamente poderoso, pero puede ser algo confuso para los usuarios que carecen de experiencia con él. Es posible que desees instalar un editor más amigable para el usuario, como nano, para facilitar la edición de archivos de configuración en tu servidor Rocky Linux 9:

  1. sudo dnf install nano

Ahora, utilizando nano o tu editor de texto favorito, crea una aplicación de muestra llamada hello.js:

  1. nano hello.js

Inserta el siguiente código en el archivo:

~/hello.js
const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Guarda el archivo y sale del editor. Si estás usando nano, presiona Ctrl+X, luego, cuando se te solicite, presiona Y y luego Enter.

Esta aplicación Node.js escucha en la dirección especificada (localhost) y puerto (3000), y devuelve “¡Hola Mundo!” con un código de éxito HTTP 200. Dado que estamos escuchando en localhost, los clientes remotos no podrán conectarse a nuestra aplicación.

Para probar tu aplicación, escribe:

  1. node hello.js

Recibirás la siguiente salida:

Output
Server running at http://localhost:3000/

Nota: Ejecutar una aplicación Node.js de esta manera bloqueará comandos adicionales hasta que la aplicación sea detenida presionando CTRL+C.

Para probar la aplicación, abre otra sesión de terminal en tu servidor y conéctate a localhost con curl:

  1. curl http://localhost:3000

Si obtienes la siguiente salida, la aplicación está funcionando correctamente y escuchando en la dirección y puerto correctos:

Output
Hello World!

Si no obtienes la salida esperada, asegúrate de que tu aplicación Node.js esté en ejecución y configurada para escuchar en la dirección y puerto correctos.

Una vez que estés seguro de que funciona, detén la aplicación (si aún no lo has hecho) presionando CTRL+C.

Paso 2 — Instalación de PM2

A continuación, instalemos PM2, un gestor de procesos para aplicaciones Node.js. PM2 permite demonizar aplicaciones para que se ejecuten en segundo plano como un servicio.

Usa npm para instalar la última versión de PM2 en tu servidor:

  1. sudo npm install pm2@latest -g

La opción -g indica a npm que instale el módulo de forma global, para que esté disponible en todo el sistema.

Primero, usemos el comando pm2 start para ejecutar tu aplicación, hello.js, en segundo plano:

  1. pm2 start hello.js

Esto también añade tu aplicación a la lista de procesos de PM2, que se muestra cada vez que inicias una aplicación:

Output
... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Como se indica arriba, PM2 asigna automáticamente un Nombre de la aplicación (basado en el nombre del archivo, sin la extensión .js) y un id de PM2. PM2 también mantiene otra información, como el PID del proceso, su estado actual y el uso de memoria.

Las aplicaciones que se ejecutan bajo PM2 se reiniciarán automáticamente si la aplicación se bloquea o se detiene, pero podemos dar un paso adicional para que la aplicación se inicie en el arranque del sistema utilizando el subcomando startup. Este subcomando genera y configura un script de inicio para lanzar PM2 y sus procesos gestionados en el arranque del servidor:

  1. pm2 startup systemd
Output
… [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

Copia y ejecuta el comando proporcionado (esto es para evitar problemas de permisos al ejecutar herramientas de Node.js como sudo):

  1. sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
Output
… [ 'systemctl enable pm2-sammy' ] [PM2] Writing init configuration in /etc/systemd/system/pm2-sammy.service [PM2] Making script booting at startup... [PM2] [-] Executing: systemctl enable pm2-sammy... Created symlink /etc/systemd/system/multi-user.target.wants/pm2-sammy.service → /etc/systemd/system/pm2-sammy.service. [PM2] [v] Command successfully executed. +---------------------------------------+ [PM2] Freeze a process list on reboot via: $ pm2 save [PM2] Remove init script via: $ pm2 unstartup systemd

Ahora, deberás hacer una edición al servicio del sistema que se generó recientemente para que sea compatible con el sistema de seguridad SELinux de Rocky Linux. Utilizando nano o tu editor de texto favorito, abre /etc/systemd/system/pm2-sammy.service:

  1. sudo nano /etc/systemd/system/pm2-sammy.service

En el bloque [Service] del archivo de configuración, reemplaza el contenido de la configuración PIDFile con /run/pm2.pid como se destaca a continuación, y agrega la otra línea Environment destacada:

/etc/systemd/system/pm2-sammy.service
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=sammy
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/home/sammy/.local/bin:/home/sammy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/sammy/.pm2
PIDFile=/run/pm2.pid
Restart=on-failure
Environment=PM2_PID_FILE_PATH=/run/pm2.pid

ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill

[Install]

Guarda y cierra el archivo. Ahora has creado una unidad de systemd que ejecuta pm2 para tu usuario durante el inicio del sistema. Esta instancia de pm2, a su vez, ejecuta hello.js.

Inicia el servicio con systemctl:

  1. sudo systemctl start pm2-sammy

Verifica el estado de la unidad systemd:

  1. systemctl status pm2-sammy

Para obtener una visión general detallada de systemd, revisa Systemd Essentials: Trabajando con Servicios, Unidades y el Diario.

Además de lo que hemos cubierto, PM2 proporciona muchos subcomandos que te permiten gestionar o buscar información sobre tus aplicaciones.

Detén una aplicación con este comando (especifica el Nombre de la Aplicación o id de PM2):

  1. pm2 stop app_name_or_id

Reinicia una aplicación:

  1. pm2 restart app_name_or_id

Lista las aplicaciones actualmente gestionadas por PM2:

  1. pm2 list

Obtén información sobre una aplicación específica utilizando su Nombre de la Aplicación:

  1. pm2 info app_name

El monitor de procesos PM2 se puede iniciar con el subcomando `monit`. Esto muestra el estado de la aplicación, el uso de CPU y memoria:

  1. pm2 monit

Tenga en cuenta que ejecutar `pm2` sin argumentos también mostrará una página de ayuda con ejemplos de uso.

Ahora que su aplicación Node.js está en funcionamiento y es gestionada por PM2, configuremos el proxy inverso.

Paso 3 — Configurar Nginx como servidor proxy inverso

Su aplicación está en funcionamiento y escuchando en `localhost`, pero necesita configurar una forma para que sus usuarios puedan acceder a ella. Configuraremos el servidor web Nginx como un proxy inverso para este propósito.

En el tutorial previo, configuró su archivo de configuración de Nginx en `/etc/nginx/conf.d/tu_dominio.conf`. Abra este archivo para editarlo:

  1. sudo nano /etc/nginx/conf.d/your_domain.conf

Dentro del bloque `server`, debería tener un bloque `location /` existente. Reemplace el contenido de ese bloque con la siguiente configuración. Si su aplicación está configurada para escuchar en un puerto diferente, actualice la parte resaltada con el número de puerto correcto:

/etc/nginx/conf.d/your_domain.conf
server {
...
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

Esto configura el servidor para responder a solicitudes en su raíz. Suponiendo que nuestro servidor está disponible en tu_dominio, acceder a https://tu_dominio/ a través de un navegador web enviaría la solicitud a hello.js, escuchando en el puerto 3000 en localhost.

Puede agregar bloques de location adicionales al mismo bloque de servidor para proporcionar acceso a otras aplicaciones en el mismo servidor. Por ejemplo, si también estuviera ejecutando otra aplicación Node.js en el puerto 3001, podría agregar este bloque de location para permitir el acceso a través de https://tu_dominio/app2:

/etc/nginx/conf.d/your_domain.conf — Optional
server {
...
    location /app2 {
        proxy_pass http://localhost:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

Una vez que haya terminado de agregar los bloques de location para sus aplicaciones, guarde el archivo y salga de su editor.

Asegúrese de no haber introducido errores de sintaxis escribiendo:

  1. sudo nginx -t

Reinicie Nginx:

  1. sudo systemctl restart nginx

Suponiendo que su aplicación Node.js está en funcionamiento y que sus configuraciones de aplicación y Nginx son correctas, ahora debería poder acceder a su aplicación a través del proxy inverso de Nginx. Pruébelo accediendo a la URL de su servidor (su dirección IP pública o nombre de dominio).

Conclusión

¡Felicidades! Ahora tiene su aplicación Node.js funcionando detrás de un proxy inverso de Nginx en un servidor Rocky Linux 9. Esta configuración de proxy inverso es lo suficientemente flexible como para proporcionar a sus usuarios acceso a otras aplicaciones o contenido web estático que desee compartir.

A continuación, es posible que desees echar un vistazo a Cómo construir una aplicación Node.js con Docker.

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-rocky-linux-9