Como Configurar uma Aplicação Node.js para Produção no Rocky Linux 9

Introdução

Node.js é um ambiente de tempo de execução JavaScript de código aberto para construir aplicações do lado do servidor e de rede. A plataforma é executada no Linux, macOS, FreeBSD e Windows. Embora seja possível executar aplicativos Node.js na linha de comando, este tutorial se concentrará em executá-los como um serviço. Isso significa que eles serão reiniciados durante a inicialização ou falha e são seguros para uso em um ambiente de produção.

Neste tutorial, você configurará um ambiente Node.js pronto para produção em um único servidor Rocky Linux 9. Este servidor executará uma aplicação Node.js gerenciada pelo PM2 e fornecerá aos usuários acesso seguro à aplicação por meio de um proxy reverso Nginx. O servidor Nginx oferecerá HTTPS usando um certificado gratuito fornecido pelo Let’s Encrypt.

Pré-requisitos

Este guia pressupõe que você tenha o seguinte:

Quando você concluir os pré-requisitos, terá um servidor exibindo a página padrão de seu domínio em https://exemplo.com/.

Passo 1 — Criando uma Aplicação Node.js

Vamos escrever uma aplicação Hello World que retorna “Hello World” para qualquer requisição HTTP. Esta aplicação de exemplo ajudará você a começar com o Node.js. Você pode substituí-la pela sua própria aplicação — apenas certifique-se de modificar a aplicação para ouvir nos endereços IP e portas apropriados.

O editor de texto padrão no Rocky Linux 9 é o vi. O vi é um editor de texto extremamente poderoso, mas pode ser um pouco difícil para usuários sem experiência. Você pode querer instalar um editor mais amigável, como o nano, para facilitar a edição de arquivos de configuração no seu servidor Rocky Linux 9:

  1. sudo dnf install nano

Agora, usando o nano ou seu editor de texto favorito, crie um exemplo de aplicativo chamado hello.js:

  1. nano hello.js

Insira o seguinte código no arquivo:

~/hello.js
const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Salve o arquivo e saia do editor. Se estiver usando o nano, pressione Ctrl+X, depois quando solicitado, Y e então Enter.

Este aplicativo Node.js escuta no endereço especificado (localhost) e porta (3000), e retorna “Olá Mundo!” com um código de sucesso HTTP 200. Como estamos ouvindo em localhost, clientes remotos não poderão se conectar à nossa aplicação.

Para testar sua aplicação, digite:

  1. node hello.js

Você receberá a seguinte saída:

Output
Server running at http://localhost:3000/

Nota: Executar um aplicativo Node.js dessa maneira bloqueará comandos adicionais até que o aplicativo seja encerrado pressionando CTRL+C.

Para testar a aplicação, abra outra sessão de terminal em seu servidor e conecte-se ao localhost com curl:

  1. curl http://localhost:3000

Se você receber a seguinte saída, a aplicação está funcionando corretamente e ouvindo no endereço e porta corretos:

Output
Hello World!

Se você não receber a saída esperada, certifique-se de que sua aplicação Node.js esteja em execução e configurada para ouvir no endereço e porta corretos.

Assim que tiver certeza de que está funcionando, encerre a aplicação (se ainda não o fez) pressionando CTRL+C.

Passo 2 — Instalando o PM2

Agora vamos instalar o PM2, um gerenciador de processos para aplicações Node.js. O PM2 torna possível a daemonização de aplicações para que elas sejam executadas em segundo plano como um serviço.

Use o npm para instalar a versão mais recente do PM2 no seu servidor:

  1. sudo npm install pm2@latest -g

A opção -g indica ao npm para instalar o módulo globalmente, tornando-o disponível em todo o sistema.

Vamos primeiro utilizar o comando pm2 start para executar sua aplicação, hello.js, em segundo plano:

  1. pm2 start hello.js

Isso também adiciona sua aplicação à lista de processos do PM2, que é exibida cada vez que você inicia uma aplicação:

Output
... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Conforme indicado acima, o PM2 atribui automaticamente um Nome da aplicação (com base no nome do arquivo, sem a extensão .js) e um id do PM2. O PM2 também mantém outras informações, como o PID do processo, seu status atual e uso de memória.

Aplicações em execução sob o PM2 serão reiniciadas automaticamente se a aplicação falhar ou for encerrada, mas podemos dar um passo adicional para fazer com que a aplicação seja iniciada na inicialização do sistema usando o subcomando startup. Este subcomando gera e configura um script de inicialização para iniciar o PM2 e seus processos gerenciados durante a inicialização do servidor:

  1. pm2 startup systemd
Output
… [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

Copie e execute o comando fornecido (isso é para evitar problemas de permissões ao executar ferramentas Node.js como sudo):

  1. sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
Output
… [ 'systemctl enable pm2-sammy' ] [PM2] Writing init configuration in /etc/systemd/system/pm2-sammy.service [PM2] Making script booting at startup... [PM2] [-] Executing: systemctl enable pm2-sammy... Created symlink /etc/systemd/system/multi-user.target.wants/pm2-sammy.service → /etc/systemd/system/pm2-sammy.service. [PM2] [v] Command successfully executed. +---------------------------------------+ [PM2] Freeze a process list on reboot via: $ pm2 save [PM2] Remove init script via: $ pm2 unstartup systemd

Agora, você precisará fazer uma edição no serviço do sistema que foi gerado para torná-lo compatível com o sistema de segurança SELinux do Rocky Linux. Usando o nano ou seu editor de texto favorito, abra o arquivo /etc/systemd/system/pm2-sammy.service:

  1. sudo nano /etc/systemd/system/pm2-sammy.service

No bloco [Service] do arquivo de configuração, substitua o conteúdo da configuração PIDFile por /run/pm2.pid conforme destacado abaixo, e adicione a outra linha Environment destacada:

/etc/systemd/system/pm2-sammy.service
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=sammy
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/home/sammy/.local/bin:/home/sammy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/sammy/.pm2
PIDFile=/run/pm2.pid
Restart=on-failure
Environment=PM2_PID_FILE_PATH=/run/pm2.pid

ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill

[Install]

Salve e feche o arquivo. Agora você criou uma unidade systemd que executa o pm2 para o seu usuário durante a inicialização. Esta instância do pm2, por sua vez, executa o hello.js.

Inicie o serviço com systemctl:

  1. sudo systemctl start pm2-sammy

Verifique o status da unidade systemd:

  1. systemctl status pm2-sammy

Para uma visão detalhada do systemd, por favor, revise Systemd Essentials: Trabalhando com Serviços, Unidades e o Jornal.

Além do que cobrimos, o PM2 oferece muitos subcomandos que permitem gerenciar ou consultar informações sobre suas aplicações.

Pare uma aplicação com este comando (especifique o Nome do App ou id do PM2):

  1. pm2 stop app_name_or_id

Reinicie uma aplicação:

  1. pm2 restart app_name_or_id

Liste as aplicações atualmente gerenciadas pelo PM2:

  1. pm2 list

Obtenha informações sobre uma aplicação específica usando seu Nome do App:

  1. pm2 info app_name

O monitor de processo PM2 pode ser acessado com o subcomando monit. Isso exibe o status da aplicação, uso de CPU e memória:

  1. pm2 monit

Note que executar pm2 sem nenhum argumento também exibirá uma página de ajuda com exemplos de uso.

Agora que sua aplicação Node.js está rodando e gerenciada pelo PM2, vamos configurar o proxy reverso.

Passo 3 — Configurando o Nginx como um Servidor Proxy Reverso

Sua aplicação está rodando e escutando em localhost, mas você precisa configurar um meio para seus usuários acessarem ela. Para isso, vamos configurar o servidor web Nginx como um proxy reverso.

No tutorial pré-requisito, você configurou sua configuração do Nginx no arquivo /etc/nginx/conf.d/your_domain.conf. Abra este arquivo para edição:

  1. sudo nano /etc/nginx/conf.d/your_domain.conf

Dentro do bloco server, você deve ter um bloco location / existente. Substitua o conteúdo desse bloco pela seguinte configuração. Se sua aplicação estiver configurada para escutar em uma porta diferente, atualize a parte destacada para o número de porta correto:

/etc/nginx/conf.d/your_domain.conf
server {
...
    location / {
        proxy_pass http://localhost:3000;
        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;
    }
...
}

Isso configura o servidor para responder a solicitações em sua raiz. Supondo que nosso servidor esteja disponível em seu_domínio, acessar https://seu_domínio/ via um navegador da web enviaria a solicitação para hello.js, ouvindo na porta 3000 em localhost.

Você pode adicionar blocos location adicionais ao mesmo bloco de servidor para fornecer acesso a outras aplicações no mesmo servidor. Por exemplo, se você também estivesse executando outra aplicação Node.js na porta 3001, poderia adicionar este bloco de localização para permitir acesso a ela via https://seu_domínio/app2:

/etc/nginx/conf.d/your_domain.conf — Optional
server {
...
    location /app2 {
        proxy_pass http://localhost:3001;
        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;
    }
...
}

Depois de adicionar os blocos de localização para suas aplicações, salve o arquivo e saia do seu editor.

Verifique se você não introduziu erros de sintaxe digitando:

  1. sudo nginx -t

Reinicie o Nginx:

  1. sudo systemctl restart nginx

Supondo que sua aplicação Node.js esteja em execução e suas configurações de aplicativo e Nginx estejam corretas, você agora deverá ser capaz de acessar sua aplicação via o proxy reverso do Nginx. Experimente acessando a URL do seu servidor (seu endereço IP público ou nome de domínio).

Conclusão

Parabéns! Agora você tem sua aplicação Node.js rodando atrás de um proxy reverso do Nginx em um servidor Rocky Linux 9. Esta configuração de proxy reverso é flexível o suficiente para fornecer acesso aos usuários a outras aplicações ou conteúdo web estático que você queira compartilhar.

Claro, você pode querer dar uma olhada em Como construir uma aplicação Node.js com Docker.

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-rocky-linux-9