PM2 y systemd
Supervisa procesos de Node.js 24 en VMs con PM2 o systemd cuando no estés en Kubernetes o Fargate.
Receta
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
# /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.targetCuándo usarlo: EC2 básico, VMs on-premise o rutas de despliegue heredadas. Prefiere contenedores + orquestador para nuevos servicios.
Ejemplo práctico
Unidad 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# Desplegar nueva versión
sudo -u nodeapp ln -sfn /opt/api/releases/20260709-abc123 /opt/api/current
sudo systemctl restart apiEcosistema PM2
// 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/nodeappLo que esto demuestra:
- systemd: proceso único, logs de journald, archivo de entorno para secretos
- PM2: modo clúster en una VM (usar cuando no está en contenedores)
- Enlace simbólico al directorio de la versión
currentpara un cambio de despliegue atómico KillSignal=SIGTERMykill_timeoutse alinean con el apagado elegante
En detalle
systemd vs PM2
| Característica | systemd | PM2 |
|---|---|---|
| Clúster en VM | Una unidad por instancia o manual | instances integrado |
| Agregación de logs | journald | Logs de PM2 + reenvío opcional |
| Recarga sin tiempo de inactividad | Reinicio de systemd con un pequeño corte | pm2 reload clúster |
| Integración con el SO | Nativo en Linux | Paquete npm de Node |
| Mejor para | Proceso único, operaciones simples | Multiproceso en una VM |
Recarga de PM2 (Clúster)
pm2 reload apiInicia nuevos workers antes de eliminar los antiguos (similar a una actualización continua). Requiere que la aplicación maneje SIGINT/SIGTERM - Apagado elegante.
Archivos de entorno
# /etc/acme/api.env (chmod 600, root:nodeapp)
NODE_ENV=production
PORT=3000
DATABASE_URL=postgres://...Nunca archivos secretos legibles por todos. Prefiere que el agente SSM obtenga los secretos al iniciar en las VMs de AWS.
Proxy inverso
Internet -> nginx (TLS) -> localhost:3000 (Node)
nginx maneja TLS y el almacenamiento en búfer de solicitudes; Node se enlaza solo a localhost si se desea.
Errores comunes
- PM2 dentro de Docker/K8s - la doble supervisión interfiere con las señales de la plataforma. Solución: un proceso
nodepor contenedor. - Ejecutar como root - riesgo de seguridad. Solución: usuario
nodeappdedicado con propiedad del sistema de archivos. - Sin
TimeoutStopSec- systemd envía SIGKILL a los 90s por defecto de forma inconsistente. Solución: explícito 30-45s que coincida con el apagado de la aplicación. pm2 startupolvidado después de reiniciar - servicio caído después del reciclaje de la instancia. Solución:pm2 savedespués de la configuración destartup.- Modo clúster + estado en memoria - sesiones rotas entre workers. Solución: sesiones pegajosas en nginx o almacenamiento de sesiones externo.
- Despliegue sin atomicidad de enlace simbólico -
dist/a medio escribir. Solución: directorios de versiones + intercambioln -sfn.
Alternativas
| Alternativa | Usar cuándo | No usar cuándo |
|---|---|---|
| systemd | VM simple de proceso único | Necesitas un clúster integrado en la VM |
| Clúster PM2 | VM multinúcleo sin contenedores | Ya estás en K8s |
| Docker en VM | Paridad de contenedores sin K8s | Poco interés en operaciones de contenedores |
| ECS/Fargate | Abandonar completamente las operaciones de VM | Requisito estricto on-premise |
Preguntas frecuentes
¿Deberían los nuevos proyectos usar PM2?
Por defecto, usa contenedores en ECS/Fargate o K8s. PM2 sigue siendo válido para VMs heredadas y configuraciones rápidas de EC2.
¿Cuántas instancias de PM2?
Coincide con los núcleos de la CPU (a menudo 2-4 en una VM de API pequeña). Mide el RSS; evita el OOM por demasiados montones.
¿Activación de socket de systemd?
Raro para servidores HTTP de Node. Enlaza el puerto en la aplicación con la variable de entorno PORT; nginx delante es más simple.
¿Rotación de logs?
journald rota automáticamente. PM2: pm2 install pm2-logrotate o reenvía a un agente de Loki/Datadog.
¿Ruta del binario de Node?
Usa la ruta absoluta /usr/bin/node o el shim de nvm en ExecStart de systemd. Documenta en el manual de operaciones.
¿Comprobaciones de salud en VM?
Comprobación de salud de ALB a /health o curl cron local con alertas. Los mismos endpoints que los contenedores.
Relacionado
- Apagado elegante - Manejo de SIGTERM
- Conceptos básicos de operaciones en tiempo de ejecución - modelo de supervisión
- Despliegues sin tiempo de inactividad - patrón de recarga de PM2
- Conceptos básicos de despliegue de plataforma - por qué los orquestadores reemplazan a PM2
- Mejores prácticas de operaciones en tiempo de ejecución - lista de verificación de la sección
Versiones de la pila: Esta página fue escrita para Node.js 24.18.0 (LTS activa), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 y NestJS 11.