PM2 & systemd
Supervisione processos Node.js 24 em VMs com PM2 ou systemd quando você não estiver no Kubernetes ou Fargate.
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
# /etc/systemd/system/api.service
[Unit]
Description=Node API
After=network.target
[Service]
Type=simple
User=nodeapp
WorkingDirectory=/opt/api
Environment=NODE_ENV=production
Environment=PORT=3000
ExecStart=/usr/bin/node dist/main.js
Restart=on-failure
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=30
[Install]
WantedBy=multi-user.targetQuando usar isso: EC2 bare metal, VMs on-premise ou caminhos de implantação legados. Prefira contêineres + orquestrador para novos serviços.
Exemplo de Trabalho
Unidade systemd
[Unit]
Description=Acme API (Node 24)
After=network-online.target
Wants=network-online.target
[Service]
User=nodeapp
Group=nodeapp
WorkingDirectory=/opt/api/current
EnvironmentFile=/etc/acme/api.env
ExecStart=/usr/bin/node --max-old-space-size=512 dist/main.js
Restart=on-failure
RestartSec=5
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=45
LimitNOFILE=65535
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable api
sudo systemctl start api
sudo journalctl -u api -f# Implanta nova versão
sudo -u nodeapp ln -sfn /opt/api/releases/20260709-abc123 /opt/api/current
sudo systemctl restart apiPM2 Ecosystem
// ecosystem.config.cjs
module.exports = {
apps: [
{
name: "api",
cwd: "/opt/api/current",
script: "dist/main.js",
instances: 2,
exec_mode: "cluster",
env: {
NODE_ENV: "production",
PORT: 3000,
},
max_memory_restart: "600M",
kill_timeout: 30_000,
listen_timeout: 10_000,
merge_logs: true,
log_date_format: "YYYY-MM-DD HH:mm:ss Z",
},
],
};pm2 start ecosystem.config.cjs
pm2 save
pm2 startup systemd -u nodeapp --hp /home/nodeappO que isso demonstra:
- systemd: processo único, logs do journald, arquivo de ambiente para segredos
- PM2: modo cluster em uma VM (use quando não estiver em contêiner)
- Diretório de lançamento
currentcom symlink para troca atômica de implantação KillSignal=SIGTERMekill_timeoutalinhados com desligamento gracioso
Mergulho Profundo
systemd vs PM2
| Recurso | systemd | PM2 |
|---|---|---|
| Cluster em VM | Uma unidade por instância ou manual | instances integrado |
| Agregação de logs | journald | Logs do PM2 + encaminhamento opcional |
| Recarga sem interrupção | Pequena interrupção na reinicialização do systemd | Cluster pm2 reload |
| Integração com o SO | Nativo no Linux | Pacote npm do Node |
| Melhor para | Processo único, operações simples | Múltiplos processos em uma VM |
PM2 Reload (Cluster)
pm2 reload apiInicia novos workers antes de matar os antigos (semelhante à atualização gradual). Requer que o aplicativo lide com SIGINT/SIGTERM - Graceful Shutdown.
Arquivos de Ambiente
# /etc/acme/api.env (chmod 600, root:nodeapp)
NODE_ENV=production
PORT=3000
DATABASE_URL=postgres://...Nunca arquivos de segredo legíveis por qualquer pessoa. Prefira o agente SSM puxando segredos na inicialização em VMs AWS.
Reverse Proxy
Internet -> nginx (TLS) -> localhost:3000 (Node)
nginx lida com TLS e bufferização de requisições; Node se vincula apenas ao localhost, se desejado.
Armadilhas
- PM2 dentro do Docker/K8s - dupla supervisão luta contra os sinais da plataforma. Correção: um processo
nodepor contêiner. - Executando como root - risco de segurança. Correção: usuário
nodeappdedicado com propriedade do sistema de arquivos. - Sem
TimeoutStopSec- systemd envia SIGKILL em 90s padrão de forma inconsistente. Correção: 30-45s explícitos correspondendo ao desligamento do aplicativo. pm2 startupesquecido após reboot - serviço inativo após reciclagem da instância. Correção:pm2 saveapós configuração dostartup.- Cluster mode + estado em memória - sessões quebradas entre workers. Correção: sessões fixas no nginx ou armazenamento de sessão externo.
- Implantação sem atomicidade de symlink -
dist/meio escrito. Correção: diretórios de lançamento + trocaln -sfn.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| systemd | VM simples de processo único | Precisa de cluster integrado na VM |
| PM2 cluster | VM multi-core sem contêineres | Já está no K8s |
| Docker na VM | Paridade de contêineres sem K8s | Apetite mínimo de operações de contêiner |
| ECS/Fargate | Deixar as operações de VM completamente | Requisito on-premise difícil |
FAQs
Novos projetos devem usar PM2?
Prefira contêineres no ECS/Fargate ou K8s. PM2 continua válido para VMs legadas e configurações rápidas de EC2.
Quantas instâncias PM2?
Corresponda aos núcleos de CPU (geralmente 2-4 em uma pequena VM de API). Meça o RSS; evite OOM de muitos heaps.
Ativação de socket systemd?
Raro para servidores HTTP Node. Vincule a porta no aplicativo com a variável de ambiente PORT; nginx na frente é mais simples.
Rotação de logs?
journald rotaciona automaticamente. PM2: pm2 install pm2-logrotate ou encaminhe para o agente Loki/Datadog.
Caminho do binário Node?
Use o caminho absoluto /usr/bin/node ou o shim nvm em ExecStart do systemd. Documente no runbook.
Verificações de integridade em VM?
Verificação de integridade do ALB para /health ou cron local curl alertando. Mesmos endpoints que os contêineres.
Relacionados
- Graceful Shutdown - tratamento de SIGTERM
- Runtime Ops Basics - modelo de supervisão
- Zero-Downtime Deploys - padrão de recarga do PM2
- Platform Deploy Basics - por que os orquestradores substituem o PM2
- Runtime Ops Best Practices - checklist da seção
Versões da Stack: Esta página foi escrita para Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 e NestJS 11.