Subindo um NodeJS rodando através do PM2 em um AWS EC2
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