Subir backend NodeJS a AWS - EC2
Tags: aws, javascript, node, tutorial
Published: 2022-10-28 17:46:08

Subir un backend de NodeJS a AWS puede ser un verdadero problema si no se tiene un concepto general de los distintos servicios que posee el servidor de Amazon, pero en esta ocasión te voy a mostrar como yo alojo mis servidores de **NodeJS en AWS sin morir en el intento**

## ¿Qué se busca hacer?
Al igual que todo en programación, existen varias maneras de llegar a un resultado similar pero con caminos distintos. A la hora de alojar un servidor de NodeJS tenemos dos alternativas fuertes que debemos tener en cuenta: deployar utilizando _Serverless_ o hacerlo mediante _EC2_. En esta guía lo haré sobre un EC2 pero te explicaré rapidamente el por qué de mi decisión y un resumen de la diferencia que hay entre hacerlo de una forma y de otra.


## Serverless vs EC2
Primero que nada, te recomiendo leer más acerca de [Serverless framework](https://www.serverless.com/) y [EC2](https://aws.amazon.com/es/ec2/) en sus perspectivos sitios oficiales.
Esta guía no se enfoca en este tema, sin embargo, de manera resumida se puede decir que Serverless lo utilizaría para proyectos que estén en constante crecimiento y necesite una curva de gastos de manera `+demanda +precio` (este no es el caso). En cambio, EC2 en mi opinión lo usaría cuando necesito tener un gasto fijo mensual con un servidor altamente configurable de acuerdo a mis necesidades. Por ese motivo, en esta oportunidad usaré EC2 aunque no descarto hacer una guía de deploy de NodeJS - AWS utilizando Serverless en un futuro.


## Requisitos previos
Esta guía está enfocada a levantar la app de 0 a 100% por ende se deberá tener :

- Cuenta de AWS creada y con acceso.

- Dominio configurado en Route53.

- Permisos necesarios en usuario de AWS para manipular dicho sistema.

- APP de NodeJS (preferentemente subida a github)

---




## #1 - Lanzar instancia EC2
Lo primero que debemos hacer es lanzar la instancia de EC2. Para eso, una vez estemos en la región que querramos lanzar la instancia (en mi caso, Ohio), vamos al panel de EC2 y seleccionamos **Lanzar la instancia**. Estando en el panel de creación de una nueva instancia, configuraremos nuestro EC2.

![EC2 Config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxm955vi7exq4u5smn2n.png)

En mi caso seleccionaré Ubuntu (puesto que es más sencillo de configurar) y le pondré de nombre NodeJS-Backend-DEV. También seleccionaré las siguientes propiedades de mi EC2 que se adaptan a mis necesidades.

![AMI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w4udzvz2awng1sbbt59x.png)

![EC2 Type](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kaldq61gtvvk14duguu0.png)


En el apartado Par de claves es importante que creemos un nuevo par de claves (el cual nos servirá para conectarnos por  terminal al EC2. En mi caso, uso **RSA** en formato **.pem**. Por último, la memoria varía dependiendo las necesidades de cada backend, y el grupo de seguridad lo veremos más adelante en esta guía.
Con todo esto configurado, ya tendremos nuestro EC2 creado correctamente: Felicidades!

![Success EC2 Creation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lqgch5s614dr44xjn1og.png)





## #2 - Grupo de seguridad
Una vez con la instancia creada correctamente, podremos crear nuestro grupo de seguridad para indicar los puertos bajo los cuales se podrá entrar y salir de nuestro EC2. En el mismo panel (home) de EC2 presionamos sobre **Grupos de seguridad** y **Crear grupo de seguridad**
Nuestro nuevo grupo de seguridad tendrá que tener la siguiente configuración

**Entrada**

- IPv4 | SSH | TCP | 22 | 0.0.0.0/0 (puerto que usaremos para la terminal)
- IPv4 | HTTP | TCP | 80 | 0.0.0.0/0 (puerto HTTP)
- IPv4 | HTTPS | TCP | 443 | 0.0.0.0/0 (puerto HTTPS)

Una vez con el grupo de seguridad, vamos hacia nuestro EC2 y le ponemos dicho grupo

![Update security group](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvc3mcxa3ce70cuixfjo.png)






## #3 - IP Elástica
Lo siguiente será configurar una dirección de ip elástica para tener una ip fija en nuestro backend. Para hacer eso, vamos a **Direcciones IP elásticas** (home de EC2) y asignamos una nueva IP elástica. Para asignar dicha IP vamos a **Asociar la dirección IP elástica**

![Assign elastic IP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r3p1yofgs3q3bksx2arl.png)

y simplemente seleccionamos nuestra instancia EC2


## #4 - Crear un subdominio a nuestra IP Elástica
Debemos crear un subdominio de tipo A a nuestra ip elástica en Route53

![Route53](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vucdnklva8i4pp785bkd.png)



## #5 - Conectarse al EC2
Con nuestro .pem descargado, abrimos una terminal en el mismo directorio donde esté dicho archivo y escribimos lo siguiente

```
ssh -i "NOMBRE-DE-MI-PEM.pem" ubuntu@ELASTIC-IP
```

y con esto estaremos dentro de nuestra instancia EC2 a través de la terminal. Felicidades
Aclaración : Si llega a fallar la conexión, intentar dar permisos al .pem
`chmod 400 NOMBRE-DE-MI-PEM.pem `




## #6 A - Instalaciones - NODE JS
Seguir los sientes comandos para instalar todo lo necesario para correr nuestro servidor de NodeJS

nvm (NodeJS pero con switch de versiones)
```
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash

```
Una vez instalado, ejecutar 

```
source ~/.bashrc 
```

Con todo esto, si ejetutamos 

> nvm ls

veremos una respuesta.
Posteriormente, para instalar una versión de NodeJS usaremos

```
nvm install VERSION
```
en mi caso, la v16.15.0. Al ejecutar otra vez nvm ls se observará la versión de node elegida

![NVM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wt14kjh86kpkztbbq7l9.png)




## #6 B - Instalaciones - GIT
Ejecutar 

```
sudo apt-get install git
```



## #7 GITHUB LOGIN
Normalmente nuestro repo será privado, por ende, habrá que iniciar sesión en Github (en mi caso) para poder clonar dicho repositorio. Desde la terminal esto no es tan sencillo, por ende, lo explicaré también en esta guía. (Simplemente explicaré como hacerlo, NO la teoría que hay detrás. En el caso de ser necesario, pedime un post sobre ese tema 🐵)
Primero, ejecutar 

```
ssh-keygen
```
para generar nuestra clave encriptada. La terminal pedirá varias instrucciones para lo cual no tendremos que rellenar ninguna. Simplementer presionar ENTER en todo lo que nos pregunte.
Posteriormente ejecutar 

```
cat ~/.ssh/id_rsa.pub
```
para así poder ver nuestra clave 

![GITHUB KEY](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxpaywb5rtmiblptqtrl.png)

copiar TODO el contenido para luego dirigirse a [github](github.com) y en settings crear una nueva key SSH

![Github ssh key](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0k2ieobr3eosn8m75hl.png)

Una vez la clave esté en github, en nuestra terminal podremos hacer un 

```
ssh git@github.com
```

terminando así, nuestro login con GITHUB

## #8 Configurando proyecto
Este es el paso más facil y amigable de todos puesto que necesitamos configurar nuestro proyecto. Para esto, tendremos que crear todos los .env necesarios así como también instalar todas las dependencias del proyecto. El objetivo es poder ejecutar nuestro proyecto sin errores. También, necesitamos saber en que puerto está corriendo nuestro proyecto




![Node JS app running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxjo6i8fl96azrllmkdt.png)



En mi caso, el proyecto está corriendo bajo el puerto **8082**


## #9 Configurando PM2
Ahora mismo nuestro servidor está corriendo y podría usarse en cualquier parte del mundo. Sin embargo, nos interesa tener el servidor ejecutandose por más que la terminal se cierre. A demás, es conveniente tener un monitor para saber tanto los recursos como logs ordenados de nuestra app. Todo esto y más hace por nosotros pm2.
Para instalar pm2 ejecutar

```
npm install pm2 -g
```

y ya tendremos instalado pm2. Para ejecutarlo, nos paramos en nuestra carpeta del proyecto y ejecutamos

```
pm2 start puntoDeEntradaDeMiApp.js
```
y podremos ver nuestra app corriendo 
![Pm2 started](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1mkuv9lts9rzfd1vxvz.png)
PM2 Es muy útil, recomiendo 100% leer más sobre él en su [web oficial](https://pm2.keymetrics.io/)



## #10 NGINX como Reverse-Proxy
Usaremos NgninX para poder así exponer nuestro servidor usandolo de reverse-proxy para posteriormente poder colocarle certificado e ingresar a través de https 🐵 ¿Suena complejo? No lo es!
A este punto, se tendrá que tener en claro cual será el subdominio que se desee utilizar.
Primero instalaremos nginx utilizando 

```
sudo apt update
sudo apt install nginx
```
En el caso de que usemos firewall ufw darle permisos a través de 

```
sudo ufw allow 'Nginx HTTP'

```
¡Listo! está instalado. Podremos confirmar que se esté ejecutando con 

```
systemctl status nginx
```
A lo que tendremos una respuesta similar a esta:

```
 nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2022-10-28 17:06:52 UTC; 4min 30s ago
       Docs: man:nginx(8)
   Main PID: 31570 (nginx)
      Tasks: 2 (limit: 1143)
     Memory: 3.2M
     CGroup: /system.slice/nginx.service
             ├─31570 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
             └─31571 nginx: worker process

Oct 28 17:06:52 ip-XXXXXXXX systemd[1]: Starting A high performance web server and a reverse proxy server...
Oct 28 17:06:52 ip-XXXXXXXX systemd[1]: Started A high performance web server and a reverse proxy server.
```
Posteriormente, configuraremos nginx utilizando el comando

```
sudo nano /etc/nginx/sites-available/TU_SUBDOMINIO
```
dentro de este archivo colocaremos lo siguiente

```
server {
    listen 80;
    listen [::]:80;

    server_name TU_SUB_DOMINIO;
        
    location / {
        proxy_pass http://127.0.0.1:PUERTO_DE_MI_APP/;
        include proxy_params;
    }
}
```
Por último, linkearemos el archivo que creamos directamente con nginx utilizando los comandos

```
sudo ln -s /etc/nginx/sites-available/TU_SUBDOMINIO /etc/nginx/sites-enabled/
sudo nginx -t (opcional - checkea sintaxis)
sudo systemctl restart nginx
```

Con todo esto hecho, podremos ya ver nuestro backend en la url http://misubdominio.com

## #11 Configurando un certificado TLS/SSL
Generalmente nos interesará que nuestro backend esté bajo el protocolo HTTPS. Para configurar dicho certificado, la opción más fácil y rápida es a través de **Certbot** para lo cual 
lo instalaremos ejecutaremos los siguientes comandos

```
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
```
Por último, para obtener el certificado utilizaremos el siguiente comando

```
sudo certbot --nginx -d MI-SUBDOMINIO 

```
Nos pedirá un mail para mandarnos publicidad 🐵 y aceptar todos los términos. Una vez aceptado todo tendremos nuestro certificado.
También, nos interesará que se renueve automaticamente para lo cual utilizaremos el comando

```
sudo systemctl status snap.certbot.renew.service
```


 ---


## Notas finales
Realmente muy interesante todo lo que hicimos a lo largo de esta guía. Espero que les haya sido útil. Todo está hecho en base a mi experiencia lo cual quiere decir que **NO** aseguro que sea la mejor forma de hacer lo que propuse. De todas maneras, estoy abierto a sugerencias... ¿Crees que podes aportar algo más a la explicación? Dejalo en comentarios!
Si querés contactarme, mi linkedin es : https://www.linkedin.com/in/oberg-agustin/