Subindo um NodeJS rodando através do PM2 em um AWS EC2

André Luiz Batista Aureliano
5 min readFeb 21, 2021

--

Aqui vou narrar como aprendi a criar uma instância de EC2 na AWS e rodar um serviço em NodeJS através do gerenciador de processos PM2 com certificado SSL configurado.

Criando uma instancia do EC2

Criando um IP Elástico e associando a sua instância

Conectar a máquina via SSH com o certificado .pem que gerou

Agora na máquina:

Atualize o Linux. Aqui estamos usando o Ubuntu, então os comandos serão para ele.

sudo apt-get updatesudo apt-get upgrade

Instale o Nginx:

sudo apt-get install nginx

Instale o UFW (Uncomplicated Firewall)

sudo apt-get install ufw

Agora vamos configurar o ufw

sudo ufw allow sshsudo ufw enablesudo ufw app listsudo ufw allow ‘Nginx Full’

Vamos instalar o Node através do NVM pra melhor controlar a versão dele, caso precisemos de trocar a versão de maneira rápida.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash

Agora instalamos o Node LTS

nvm install --lts

Assim que concluir a instalação, muito provavelmente, o NVM não estará disponível, então você deve fechar o terminal e abrir de novo(ou fechar a conexão SSH e acessar novamente)

Pra ter certeza que instalou tudo nos conformes:

nvm -vnode -vnpm -v

Vamos instalar o PM2 globalmente:

npm i -g pm2

Agora iremos criar a estrutura de pastas, que irão se encaixar bem com um futuro CI implementado.

Vamos criar 2 pastas: builds e domains.
Na pasta builds, teremos cada branch e commit buildados, fora do alcance do público.
Na pasta domains teremos a pasta pública e um link simbólico para a pasta build.

cd /usr/share/nginx/
mkdir builds domains files

Dentro de builds vamos criar uma pasta com o nome do repositório e uma pasta pra a branch master e outra pra staging

cd buildsmkdir nome-do-repocd nome-do-repomkdir master staging

Vamos entrar na pasta master e clonar o repositório (Estamos usando o Gitlab):

git clone git@gitlab.com:player2.tech/nome-do-repo.git .

Aqui provavelmente irá retornar um erro porque você não adicionou a chave SSH dessa máquina pra ter acesso a essa conta. Vamos criar a chave:

ssh-keygen

Enter até chegar ao fim

cat /home/ubuntu/.ssh/id_rsa.pub

Copie o conteúdo que printou no terminal e adicione como uma SSH KEY na sua conta do GitLab

Agora repita o git clone, na pasta correta:

cd /home/ubuntu/builds/nome-do-repo/mastergit clone git@gitlab.com:player2.tech/nome-do-repo.git .

Repo clonado? Agora vamos instalar as dependencias:

npm install

Beleza! Tudo ok!

Precisamos criar nossa pasta lá em domains

cd /home/ubuntu/domainsmkdir nome-do-dominiocd nome-do-dominiomkdir public

Vamos criar um link simbólico entre as pastas publicas de builds e domains

ln -sfn /home/ubuntu/builds/nome-do-repo/master/public /home/ubuntu/domains/nome-do-dominio/public

Hora de instalar o Certificado SSL usando o Certbot

Primeiro tenha certeza que o DNS está configurado certo pra seu IP. Eu uso o cloudflare e é super simples.

Antes de solicitar os certificados, temos que criar uma configuração básica do nginx para quando o certificado tentar acessar, ele ser aceito:

Vá até:

cd /etc/nginx/sites-availablemkdir SEU-DOMINIO.confsudo nano SEU-DOMINIO.conf

Coloque o seguinte conteúdo:

upstream nodejsAPI {
server 127.0.0.1:3333 max_fails=0;
}
server {
listen 80;
listen [::]:80;
server_name SEU-DOMINIO;
root /var/www/domains/SEu-DOMINIO;
index index.html index.htm;
}

No site do CertBot ensina como fazer isso(https://certbot.eff.org/lets-encrypt/ubuntufocal-nginx.html), mas vamos seguir aqui também

sudo snap install core; sudo snap refresh coresudo snap install --classic certbotsudo ln -s /snap/bin/certbot /usr/bin/certbotsudo certbot certonly -d nome-do-dominio --nginxsudo certbot renew --dry-runsudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Vamos conferir se está tudo ok:

sudo nginx -t

Agora reiniciar o Nginx:

sudo systemctl restart nginx

Vamos criar um arquivo .conf pra esse domínio que criamos:

cd /etc/nginx/sites-availablesudo nano nome-do-dominio.conf

Uma vez aberto o Nano você vai colar essa configs e alterar o nome-do-dominio e a porta que seu serviço está rodando:

upstream nodejsNOMEDODOMINIO { server 127.0.0.1:3333 max_fails=0;}server {listen       80;listen       [::]:80;server_name  NOME-DO-DOMINIO;return 301 https://NOME-DO-DOMINIO$request_uri;}server {listen       443 ssl http2;listen       [::]:443 ssl http2;server_name  NOME-DO-DOMINIO;root         /home/ubuntu/domains/NOME-DO-DOMINIO/public;#root /usr/share/nginx/html;index index.html index.htm;ssl_certificate "/etc/letsencrypt/live/NOME-DO-DOMINIO/fullchain.pem";ssl_certificate_key "/etc/letsencrypt/live/NOME-DO-DOMINIO/privkey.pem";ssl_session_cache shared:SSL:1m;ssl_session_timeout  10m;ssl_session_tickets off;# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bitsssl_dhparam /etc/ssl/certs/dhparam.pem;# enables server-side protection from BEAST attacks# http://blog.ivanristic.com/2013/09/is-beast-still-a-threat.htmlssl_prefer_server_ciphers on;# disable SSLv3(enabled by default since nginx 0.8.19) since it's less secure then TLS http://en.wikipedia.org/wiki/Secure_Sockets_Layer#SSL_3.0ssl_protocols TLSv1.2 TLSv1.3;# ciphers chosen for forward secrecy and compatibility# http://blog.ivanristic.com/2013/08/configuring-apache-nginx-and-openssl-for-forward-secrecy.htmlssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';# enable ocsp stapling (mechanism by which a site can convey certificate revocation information to visitors in a privacy-preserving, scalable manner)# http://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/resolver 8.8.8.8 8.8.4.4;ssl_stapling on;ssl_stapling_verify on;# Load configuration files for the default server block.#include /etc/nginx/default.d/*.conf;location / {#try_files $uri $uri/ /index.html;proxy_pass  http://nodejsNOMEDODOMINIO;proxy_redirect off;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 https;}error_page 404 /404.html;location = /40x.html {}error_page 500 502 503 504 /50x.html;location = /50x.html {}}

Vamos conferir novamente se o Nginx está ok:

sudo nginx -t

Agora vamos criar um link simbólico entre o arquivo da pasta sites-available e sites-enabled

sudo ln -s /etc/nginx/sites-available/nome-do-dominio.conf /etc/nginx/sites-enabled/nome-do-dominio.conf

Estando tudo 100%, podemos reiniciar o serviço

sudo systemctl restart nginx

Agora vamos rodar o Node usando o pm2

Vá até a pasta build

cd /home/ubuntu/builds/nome-do-repo/masterpm2 start server.js --name NOME-DO-SERVICO --log-date-format "DD-MM-YYYY HH:mm:ss"

Altere o comando do pm2 para executar o arquivo de entrada do seu sistema em Node. No nosso caso, estamos trabalhando com o AdonisJS e o arquivo de entrada é o server.js.

Os demais parâmetros servem para formatar os logs colocando a data e hora no padrão brasileiro.

Instale o Glances para monitorar de uma maneira mais fácil o uso de CPU e Memória do servidor:

sudo apt-get install glances
glances

Pronto, agora teste se seu site está online!

SUCESSO!!!

--

--

André Luiz Batista Aureliano

Tech Lead Engineer @ InHire . Entrepeneur, Web/App Software Developer. “Hitting the head on the keyboard, until something goods happens”