Skip to content

Instantly share code, notes, and snippets.

@Gustavo-Kuze
Last active June 13, 2024 00:37
Show Gist options
  • Save Gustavo-Kuze/9fe3e14babc2fe0115f7ed3e8a2264dc to your computer and use it in GitHub Desktop.
Save Gustavo-Kuze/9fe3e14babc2fe0115f7ed3e8a2264dc to your computer and use it in GitHub Desktop.
Configurar nginx pm2 node via ssh

Como configurar uma API Node Express via SSH

Aluguei um servidor da letscloud.io para testar os serviço, e como a configuração inicial foi bem complexa, irei deixar o passo a passo registrado aqui.

NOTA:

  1. Caso o servidor tenha sido criado na Hostinger, o passo "Configuração inicial da máquina remota" não é necessário
  2. Neste caso também, deve-se seguir primeiramente o tutorial de Como Configurar VPS em 5 Passos Simples

Configuração inicial da máquina remota

  1. Acesse o painel da Let's Cloud e crie uma nova instância de máquina, com Ubuntu 20.04 LTS
  2. Garanta que o provedor de domínio está apontando para os name servers da LetsCloud (mostrados abaixo nos registros NS)
  3. Acesse a aba DNS Any Cast e adicione os seguintes registros:
Type Name Value TTL
A yourdomain.com.br ip.da.maquina 3600
A www ip.da.maquina 3600
CNAME autodiscover autodiscoverredirection.letscloud.io 3600
NS yourdomain.com.br ns1.letscloud.io 86400
NS yourdomain.com.br ns2.letscloud.io 86400
NS yourdomain.com.br ns3.letscloud.io 86400
NS yourdomain.com.br ns4.letscloud.io 86400
TXT yourdomain.com.br v=spf1 include:spf.letscloud.io~ all 3600

Acesse o terminal via SSH

  1. No git bash, execute o comando
ssh usuario@ip.da.maquina
  1. Aceitar fingerprint
  2. Colar senha de acesso

Intalando o NodeJS 12

  1. Faça download do Node 12 via terminal
curl -sL https://deb.nodesource.com/setup_12.x -o nodesource_setup.sh
  1. Execute o script de configuração baixado
sudo bash nodesource_setup.sh
  1. Efetive a instalação do Node
sudo apt install nodejs
  1. Instale os pacotes necessários para compilar o Node
sudo apt install build-essential
  1. Crie um servidor Express de teste
nano hello.js

cole o conteúdo de teste

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})
  1. Instale o pm2
sudo npm install pm2@latest -g
  1. Execute o app de teste com pm2
pm2 start hello.js
  1. Teste no localhost da máquina remota se é possível realizar requisições ao app de teste
curl http://localhost:3000
  1. Configure o pm2 para iniciar junto ao boot do sistema
pm2 startup systemd
  1. Instale o nginx
sudo apt update
sudo apt install nginx
  1. Crie os arquivos de configuração do nginx

sudo ufw app list

sudo ufw status

sudo ufw allow 'Nginx HTTP'

sudo ufw status

systemctl status nginx

sudo mkdir -p /var/www/your_domain/html

sudo chown -R $USER:$USER /var/www/your_domain/html

sudo chmod -R 755 /var/www/your_domain

nano /var/www/your_domain/html/index.html

// cole o conteúdo do html

<html>
    <head>
        <title>Welcome to your_domain!</title>
    </head>
    <body>
        <h1>Success!  The your_domain server block is working!</h1>
    </body>
</html>

// crie um arquivo de configuração separado

sudo nano /etc/nginx/sites-available/your_domain

// cole o conteúdo

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

        root /var/www/your_domain/html;
        index index.html index.htm index.nginx-debian.html;

        server_name your_domain www.your_domain;

        location / {
                try_files $uri $uri/ =404;
        }
}

// crie um link para o arquivo

sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/

// descomente a diretiva #server_names_hash_bucket_size, tirando o #

sudo nano /etc/nginx/nginx.conf

...
http {
    ...
    server_names_hash_bucket_size 64;
    ...
}
...

sudo nginx -t

sudo systemctl restart nginx

  1. Crie um proxy reverso da porta 3000 que possa ser acessada externamente
sudo nano /etc/nginx/sites-available/your_domain

Cole o conteúdo do arquivo

server {
        listen 80;
        listen [::]:80;
        server_name www.yourdomain.com.br;
        return 301 $scheme://yourdomain.com.br$request_uri;
}

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

        root /var/www/yourdomain.com.br/html;
        index index.html index.htm index.nginx-debian.html;

        server_name yourdomain.com.br;

        location /apiemoutraporta {
        proxy_pass http://127.0.0.1:5504;
        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;
    }

        location / {
        proxy_pass http://127.0.0.1:5503;
        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;
    }
}


Nota: /apiemoutraporta poderia ser um segundo processo que roda na porta 5504 e é acessado através da url: www.yourdomain.com.br/apiemoutraporta. Nessa segunda API você precisa configurar o express para responder às rotas da mesma forma:


app.use("/apiemoutraporta/api/", routes);

app.use(
  "/apiemoutraporta/api/media",
  express.static(
    path.join(
      __dirname,
      process.env.MODE === "development" ? "./dist/media" : "./media"
    )
  )
);

app.use("/apiemoutraporta/.well-known", express.static(path.join(__dirname, "./.well-known")));

app.use("/apiemoutraporta/inicio", express.static(path.join(__dirname, "./landing")));

app.use("/apiemoutraporta/", express.static(path.join(__dirname, "./admin")));

app.get("/apiemoutraporta/*", (req, res) => {
  res.sendFile(path.join(`${__dirname}/admin/index.html`));
});


  1. Verifique se a configuração do nginx está OK
sudo nginx -t
  1. Reinicie o nginx
sudo systemctl restart nginx

NOTA: Caso ocorra alguma erro para iniciar o nginx no Ubuntu 20.04, possivelmente é porque o Apache está utilizando a porta 80 Para resolver, basta desabilitaar/remover o Apache: https://www.cyberciti.biz/faq/how-do-i-stop-apache-from-starting-on-linux/

Clone o repositório do projeto

  1. Crie token de acesso do Github

  2. Configure seu usuário git na máquina remota

git config user.name --global "Gustavo-Kuze"

git config user.email --global "gustavoksilva3@hotmail.com"

git config -l

git clone https://github.com/yourdomain/restaurant-api.git

Nota: Quando solicitado pela senha no terminal, cole Token de acesso pessoal do Github

  1. Instale as dependências do seu projeto
npm i -g yarn

yarn

nano .env
  1. Faça o build do projeto
yarn build
  1. Inicie o projeto com pm2
pm2 start ./dist/index.js -n api

Configurando HTTPS (SSL)

  1. Instalar as dependências do cert bot
sudo apt install certbot python3-certbot-nginx
  1. Habilite o tráfego HTTPS no nginx
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
  1. Obtenha o certificado Let's Encrypt via cert bot
sudo certbot --nginx -d yourdomain.com.br -d www.yourdomain.com.br
  1. Entre com o e-mail do responsável
  2. Concorde com os termos
  3. Selecione a opção para redirecionar todo o tráfego HTTP para HTTPS
  4. Em teoria está tudo certo e seu site já pode ser acesso de maneira segura com HTTPS! 🥳

DICA: O certificado Let's Encrypt só é válido por um período de 90 dias, e precisa ser atualizado para que o HTTPS continue funcionando. O Cert bot possui a funcionalidade de auto atualização e ela pode ser verificada da seguinte maneira:

Rode o comando para verificar se o timer está ativo:

sudo systemctl status certbot.timer

O output deve ser algo semelhante à:

● certbot.timer - Run certbot twice daily
     Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Mon 2020-05-04 20:04:36 UTC; 2 weeks 1 days ago
    Trigger: Thu 2020-05-21 05:22:32 UTC; 9h left
   Triggers: ● certbot.service

É também possível simular o processo de atualização automática de certificado, executando o seguinte comando:

sudo certbot renew --dry-run

O resultado deve ser algo semelhante à:

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/yourdomain.com.br.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
Plugins selected: Authenticator nginx, Installer nginx
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for yourdomain.com.br
http-01 challenge for www.yourdomain.com.br
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed with reload of nginx server; fullchain is
/etc/letsencrypt/live/yourdomain.com.br/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/yourdomain.com.br/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.

Configurando a sincronização do repositório automática

É possível realizar o git pull e instalação de dependências do projeto automaticamente (com yarn, por exemplo) da seguinte maneira:

  1. Crie um repositório vazio na raiz do seu servidor
git init --bare ~/projeto.git
  1. Crie um post-receive hook do git
nano /projeto.git/hooks/post-receive

cole

#!/bin/bash
TARGET="/pasta/de/deploy"
GIT_DIR="/projeto.git"
BRANCH="main"

while read oldrev newrev ref
do
        # only checking out the master (or whatever branch you would like to deploy)
        if [ "$ref" = "refs/heads/$BRANCH" ];
        then
                echo "Ref $ref received. Deploying ${BRANCH} branch to production..."
                git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
        else
                echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
        fi
done

cd /pasta/de/deploy && yarn
pm2 restart api
  1. Torne-o executável
chmod +x post-receive
  1. Adicione o repositório remoto ao seu git local
git remote add production root@ip-da-maquina-remota:projeto.git
  1. dê um git push e veja seu código sendo atualizado como em um passe de mágica 🤯
git push production main

Como habilitar o FTP para editar os arquivos remotos de maneira mais fácil

https://phoenixnap.com/kb/install-ftp-server-on-ubuntu-vsftpd

Referências utilizadas

https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-20-04-pt

https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04

https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-20-04

https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04

https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04

https://gist.github.com/noelboss/3fe13927025b89757f8fb12e9066f2fa#file-post-receive

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment