Original article: How to Deploy a Node.js App – From Server Setup to Production

En este tutorial, aprenderemos todo lo que necesitamos saber antes de implementar una aplicación Node en un servidor de producción.

Comenzaremos alquilando un servidor en Digital Ocean. Luego configuraremos este servidor, nos conectaremos a él, instalaremos Nginx y lo configuraremos, extraeremos o crearemos nuestra aplicación Node y la ejecutaremos como un proceso.

Como puedes ver, hay mucho que hacer y será un tutorial lleno de acción. Así que comencemos sin perder tiempo.

Debes tener algunos conocimientos básicos sobre cómo funciona la Terminal y cómo trabajar con Vi/Vim antes de comenzar. Si no estás familiarizado con los comandos básicos, te aconsejo que los leas un poco.

Ejecutaré los comandos en MacOS. Si quieres seguir este tutorial en Windows, puedes usar Powershell o algún otro emulador de Unix de tu elección.

Aunque usaré Node.js como plataforma de nuestra aplicación de ejemplo, la mayoría de los pasos son los mismos para cualquier aplicación web.

¿Por qué Digital Ocean?

Elijo Digital Ocean porque es barato y la interfaz es realmente fácil de usar, en comparación con AWS. Además, se incluye un crédito de $100 en el paquete de estudiante de GitHub para que no tengas que pagar nada durante un par de meses. Es ideal para implementar un curso o un proyecto de pasatiempos.

Tiene un concepto llamado Droplets, que es básicamente tu parte de un servidor. Puedes imaginar el servidor como un apartamento del que eres propietario o un apartamento alquilado.

Los droplets funcionan con la ayuda de máquinas virtuales que se ejecutan en el servidor. Entonces, un Droplet es tu máquina virtual en un servidor compartido. Dado que es una máquina virtual, su uso compartido de CPU y memoria se puede aumentar fácilmente, generalmente invirtiendo más dinero en tu proveedor.

Cómo crear un proyecto de Digital Ocean

This image has an empty alt attribute; its file name is image-3.png

Supongo que ya te has registrado e iniciado sesión en Digital Ocean antes de continuar. Primero debemos crear un proyecto que contenga nuestros droplets. Hagamos clic en el botón de nuevo proyecto en el menú del lado izquierdo. Te pedirá que nombres tu proyecto.

This image has an empty alt attribute; its file name is Screen-Shot-2021-02-22-at-13.35.06.png

Introduce el nombre que quieras. También te preguntará si quieres mover algún recurso, pero por ahora simplemente haz clic en Omitir; crearemos el droplet más tarde.

Cómo crear un droplet en Digital Ocean

Vamos a crear nuestro droplet haciendo clic en el botón Comenzar.

This image has an empty alt attribute; its file name is image-4-1024x593.png

Después de hacer clic en el botón, nos pedirá que elijamos una imagen de VM (Máquina virtual).

This image has an empty alt attribute; its file name is Screen-Shot-2021-02-22-at-13.12.43-1024x567.png
Elegir una imagen

En esta página, seleccionaré Ubuntu 20.04, ya que es la última versión de LTS en el momento en que escribo esta publicación. LTS significa "Soporte a largo plazo" (por sus siglas en inglés). Lo mejor es optar por la versión LTS para proyectos reales, porque el proveedor garantiza que será compatible y mantenido durante mucho tiempo. Esto significa que no tendrás problemas a largo plazo.

Elegí Ubuntu y te lo recomendaría, ya que es la distribución de Linux más utilizada. Esto significa que también es más fácil encontrar respuestas a tus dudas futuras.

También puedes optar por tener una CPU dedicada si la necesitas. Si estás construyendo tu propia startup o cualquier proyecto comercial, te recomendaría leer esta publicación que contiene instrucciones detalladas sobre cómo elegir la opción adecuada para ti.

Seguiré con la opción más barata en este caso.

Luego, deberás seleccionar una región del centro de datos. Debes elegir el que esté más cerca de ti para minimizar el retraso de la red.

This image has an empty alt attribute; its file name is image-2-1024x519.png
Seleccionar un centro de datos

A continuación, seleccionemos Claves SSH como el Método de autenticación, ya que es mucho más seguro que la autenticación de contraseña básica.

This image has an empty alt attribute; its file name is image-5-1024x459.png
Método de autenticación

Para conectarnos al servidor necesitamos generar una nueva clave SSH en nuestro propio dispositivo y agregarla a Digital Ocean.

Cómo generar una clave SSH

Generaré la clave en mi dispositivo macOS. Si estás utilizando Windows, puedes consultar este artículo. Abre tu terminal y muévete a la carpeta ssh:

cd ~/.ssh

Luego crea tu clave SSH:

ssh-keygen

Si tu computadora dice que no conoce este comando, debes instalarlo a través de brew.

This image has an empty alt attribute; its file name is image-7-1024x140.png

Te pedirá que asignes un nombre al archivo e ingreses una frase de contraseña. No ingreses un nombre, solo presiona enter y sigue con los valores predeterminados. Deberías tener estos archivos generados. He nombrado el mío digital-ocean-ssh en esta captura de pantalla, así que no te confundas con eso.

❯ lsid_dsa      id_rsa      known_hosts

Nuestra clave pública es el id_dsa y el id_rsa es nuestra clave privada. Si olvidas cuál es la privada, siempre puedes imprimir una de ellas para verla.

Cómo agregar tu clave SSH a Digital Ocean

Ahora queremos copiar nuestra clave pública y subirla a Digital Ocean para que sepan qué clave usar en la autenticación.

This image has an empty alt attribute; its file name is image-9-1024x149.png

Copia toda esta clave, incluida la parte ssh-rsa.

Haz clic en "Nueva clave SSH":

This image has an empty alt attribute; its file name is image-10.png

Pega la clave en el cuadro de texto que aparece después de hacer clic en el botón y deberías ver tu clave SSH.

This image has an empty alt attribute; its file name is image-11.png

Cómo conectarse al servidor

Usaremos la terminal para conectarnos a nuestro servidor con SSH. Si quieres también puedes echar un vistazo a Termius para obtener una buena interfaz.

Ejecuta este comando en tu terminal después de reemplazar IP_ADDRESS con la dirección IP de tu servidor (puedes buscarla desde el panel de Digital Ocean).

ssh root@IP_ADDRESS

Si todo va bien, ahora deberías estar en la terminal del servidor. Nos hemos conectado con éxito al servidor. Si hay algún error, puedes depurarlo ejecutando el comando con la opción "-v" o "-vv" para obtener aún más detalle.

Cómo configurar el servidor

Necesitamos hacer una configuración inicial antes de implementar la aplicación Node en el servidor.

Actualizar el software

Queremos actualizar el software del servidor para asegurarnos de que estamos usando las últimas versiones.

Muchos servidores son vulnerables a los ataques porque utilizan versiones anteriores de software con vulnerabilidades conocidas. Los atacantes pueden buscar las vulnerabilidades en ese software e intentar explotarlas para obtener acceso a tu servidor.

Puedes actualizar el software de Ubuntu usando el comando "apt update" .

apt updateHit:1 https://repos.insights.digitalocean.com/apt/do-agent main InReleaseGet:2 http://mirrors.digitalocean.com/ubuntu focal InRelease [265 kB]      Hit:3 http://mirrors.digitalocean.com/ubuntu focal-updates InRelease                Get:4 http://security.ubuntu.com/ubuntu focal-security InRelease [109 kB]Hit:5 http://mirrors.digitalocean.com/ubuntu focal-backports InReleaseFetched 374 kB in 1s (662 kB/s)                          Reading package lists... DoneBuilding dependency tree       Reading state information... Done96 packages can be upgraded. Run 'apt list --upgradable' to see them.

Si lees el mensaje, dice que "se pueden actualizar 96 paquetes". Hemos instalado los nuevos paquetes de software, pero aún no hemos actualizado nuestro software a esas versiones.

Para hacer eso, ejecutemos otro comando:

apt upgrade

Escribe 'y' cuando se te solicite y actualizarás el software.

Crear un usuario

Nos hemos conectado al servidor como el usuario root (el usuario con mayores privilegios). Ser root es peligroso y puede exponernos a vulnerabilidades.

Por lo tanto, debemos crear un nuevo usuario y no ejecutar comandos como root. Reemplaza $usernamecon un nombre de usuario de tu elección.

whoamiroot
adduser $username

Es necesario introducir una contraseña para el usuario. Después de ese punto, hará un montón de preguntas, así que sigue avanzando hasta que terminen las indicaciones.

Se ha creado el nuevo usuario, pero también debemos agregar este nuevo usuario al grupo "sudo" para que podamos realizar cualquier acción que necesitemos.

usermod -aG sudo $USERNAME

Agregamos grupo con la opción -aG (agregar grupo), y agregamos el nombre del grupo sudoa nuestro nombre de usuario.

Todavía somos root, así que cambiemos nuestro usuario al usuario recién creado, usando el comando su (cambiar de usuario).

su $USERNAME

Después de este punto, si ejecutas el comando whoami, deberías ver tu nombre de usuario. Puedes confirmar la existencia del grupo sudo ejecutando este comando:

sudo cat /var/log/auth.log

Solo los superusuarios pueden ver este archivo y el sistema operativo te pedirá tu contraseña de usuario después de ejecutar este comando.

Copia la clave SSH

Hemos creado correctamente el usuario, pero aún no hemos habilitado el inicio de sesión SSH para este nuevo usuario.

Por lo tanto, tenemos que copiar la clave pública que creamos previamente en nuestro ordenador local y pegarla en la carpeta SSH de este usuario para que SSH pueda saber qué clave debe usar para autenticar a nuestro nuevo usuario.

mkdir -p ~/.ssh

El argumento -p crea el directorio si no existe.

vi ~/.ssh/authorized_keys

Usaremos vi o vim para crear un archivo y llamarlo authorized_keys.

Copia tu clave pública (archivo `id_dsa`) y luego presiona "i" para entrar en el modo de inserción. Luego simplemente pégalo en este archivo con CMD + V (En Mac, si usas PC -> CTRL + V).

Presiona esc para salir del modo de inserción, escribe :wq para guardar y salir.

Si tienes algún problema con el uso de Vim-Vi, puedes consultar uno de los muchos tutoriales que explican cómo usarlo.

Conectarse al servidor con el nuevo usuario

Ahora deberíamos poder conectarnos al servidor sin ningún problema usando ssh. Puedes usar este comando para conectarte, solo recuerda insertar tu nombre de usuario ($USERNAME) y dirección ip (IP_ADDRESS).

ssh $USERNAME@IP_ADDRESS

Si tienes algún problema en este punto, simplemente debes eliminar el droplet y comenzar de nuevo. No toma mucho tiempo comenzar de nuevo, pero la depuración de problemas del servidor puede ser difícil.

Cómo deshabilitar el inicio de sesión con root

Es una buena práctica deshabilitar el inicio de sesión de root como medida de seguridad, así que hagámoslo ahora.

Puede ser útil cambiar el permiso del archivo por si acaso para que no tengamos problemas con los permisos en el futuro.

chmod 644 ~/.ssh/authorized_keys

Ahora abramos nuestro archivo sshd_config:

sudo vi /etc/ssh/sshd_config

Encuentra esta línea y cambia el sí por el no de la misma manera que lo hicimos antes con vi.

PermitRootLogin no

Guardar y salir de vi.

Cómo instalar Node.js y Git

Ya podemos continuar e instalar Node.js y Git:

sudo apt install nodejs npm
sudo apt install git

Ahora estamos listos para crear una aplicación Node y ejecutarla. Puedes extraer tu proyecto de Node de Github o crear una aplicación de Node aquí para probar si funciona.

Ves a un directorio de tu elección y crea un archivo "app.js" :

sudo vi app.js

Puedes pegar el siguiente fragmento en tu archivo app.js :

const express = require('express');const app = express();const port = 3000;app.get('/', (req, res) => {        res.send('Hola Mundo');});app.listen(port, () => console.log(`¡Aplicación de ejemplo escuchando en el puerto ${port}!`));

Ahora podemos ejecutarlo con el comando:

node app.js

Deberías ver "¡Aplicación de ejemplo escuchando en el puerto 3000!" en tu terminal.

Podemos confirmar que está funcionando enviando una solicitud a nuestro servidor:

GET http://IP_ADDRESS:3000/

Envía esta solicitud desde un cliente HTTP como Postman o tu navegador y deberías ver el mensaje "Hola Mundo".

En este punto, deberías notar que algo no está bien: Los usuarios regulares no saben cómo enviar solicitudes al puerto 3000.

Deberíamos redirigir las solicitudes que llegan a nuestro servidor web desde nuestra IP al puerto 3000. Esto lo podemos lograr con la ayuda de Nginx.

This image has an empty alt attribute; its file name is image-16.png

Cómo instalar y configurar Nginx

Usaremos Nginx como proxy inverso para redirigir las solicitudes a nuestra aplicación Node.

This image has an empty alt attribute; its file name is image-14-1024x531.png
Nginx como proxy inverso

Instalamos Nginx:

sudo apt install nginx

Inicia el servicio Nginx:

sudo service nginx start

Podemos probar para ver si funciona enviando una solicitud a la dirección IP de nuestro servidor desde el navegador. Escribe la dirección IP de tu servidor en tu navegador y deberías ver esto:

This image has an empty alt attribute; its file name is image-15-1024x231.png

Es importante saber que Nginx sirve desde "/var/www/html" de forma predeterminada y también puedes encontrar este archivo HTML en ese directorio.

También te aconsejo que crees una carpeta en "/var/www", llámala app y mueve tu aplicación Node a esa carpeta para que sea fácil de encontrar.

Cómo configurar el proxy inverso de Nginx

Editaremos el archivo de configuración de Nginx para configurar un proxy inverso:

sudo vi /etc/nginx/sites-available/default

En este archivo, debes encontrar la ubicación / block y cambiarla de la siguiente manera:

location / {                # First attempt to serve request as file, then                # as directory, then fall back to displaying a 404.                proxy_pass http://127.0.0.1:3000/;        }

La directivaproxy_pass envía la solicitud a un puerto específico. Damos el puerto en el que se ejecuta nuestra aplicación Node.

Reiniciamos Nginx para que los cambios surtan efecto:

sudo service nginx reload

Después de este paso, deberíamos poder ver el mensaje cuando enviamos una solicitud a nuestro servidor. ¡Felicidades, hemos completado la cantidad mínima de pasos para implementar una aplicación Node!

This image has an empty alt attribute; its file name is Screen-Shot-2021-02-24-at-01.10.33-1024x67.png

Pero aún así te aconsejo que completes el siguiente paso también, ya que creo que es bastante importante.

Si no puedes ver el mensaje de hola mundo, puedes verificar si tu aplicación y Nginx se están ejecutando y reiniciarlos.

Cómo ejecutar tu aplicación como un proceso

No queremos iniciar nuestra aplicación manualmente cada vez que algo salga mal y nuestra aplicación falle. Queremos que se reinicie solo. Además, cada vez que se inicia el servidor, nuestra aplicación también debería iniciarse.

Para que esto suceda, podemos usar PM2. Instalemos PM2 y configuremos.

sudo npm i -g pm2

Estamos instalando pm2 globalmente usando la opción "-g" para que sea accesible desde todas las carpetas.

pm2 start app.js

Esto asegura que la aplicación se reinicie si se cierra debido a un error.

Guardemos la lista de procesos actual.

pm2 save

También necesitamos convertirlo en un demonio que se ejecute cada vez que se inicie el sistema:

pm2 startup systemd
This image has an empty alt attribute; its file name is image-17.png

Como recordatorio, en este tutorial estoy usando los comandos para Ubuntu. Si estás utilizando cualquier otra distribución de Linux, debes reemplazar systemd en este comando.

Podemos confirmar que el servicio se reinicia reiniciando el servidor y enviando una solicitud sin ejecutar app.js a mano:

sudo reboot

Después de enviar una solicitud como lo hicimos anteriormente, deberías poder ver el mensaje de hola mundo.

Conclusión

En este tutorial, comenzamos desde cero, alquilamos un servidor, nos conectamos y lo configuramos de manera que sirve nuestra aplicación Node.js desde el puerto 80.

Si has seguido y has podido completar todos los pasos, ¡felicidades! Puedes estar orgulloso de ti mismo, ya que este tema no es de lo más fácil :). Espero que hayas aprendido mucho. Gracias por tu tiempo.

Planeo explorar más este tema conectando el servidor a un nombre de dominio y luego conectándolo a CircleCI para una integración continua. También revisaré los pasos necesarios para preparar la producción de tu aplicación Node.js/React. Sin embargo, esta publicación ya se había hecho lo suficientemente larga, por lo que esos temas están reservados para otra publicación :)

Si te ha gustado la lectura y quieres estar informado de mis futuras publicaciones, puedes suscribirte a mi blog personal . Puedes ver mis publicaciones anteriores allí si estás interesado en leer más. Suelo escribir sobre temas relacionados con el desarrollo web.