/** * PM2 Ecosystem Config — Zulip Gateway v3 (Resilience) * * Deploy: pm2 start /root/.pm2/ecosystem.config.cjs * Status: pm2 status * Logs: pm2 logs abiba-zulip */ module.exports = { apps: [ { // ── Router (main Zulip gateway) ── name: "abiba-zulip", script: "/bin/pi", args: "--mode rpc --session-id zulip-service", cwd: "/root", // Resilience hardening — up from pi defaults max_restarts: 100, // Crash loops won't exhaust PM2 (was default 10) min_uptime: "10s", // Must survive 10s to count as "alive" max_memory_restart: "500M", // OOM protection — restart before swap thrash restart_delay: 5000, // 5s cooldown between restarts kill_timeout: 15000, // 15s SIGTERM grace before SIGKILL listen_timeout: 30000, // 30s to bind health port // Logging log_date_format: "YYYY-MM-DD HH:mm:ss Z", error_file: "/root/.pm2/logs/abiba-zulip-error.log", out_file: "/root/.pm2/logs/abiba-zulip-out.log", merge_logs: true, log_type: "json", // Process management autorestart: true, watch: false, instances: 1, exec_mode: "fork", // Environment env: { ZULIP_ROLE: "router", ZULIP_SITE: "https://chat.sysloggh.net", ZULIP_EMAIL: "abiba-bot@chat.sysloggh.net", ZULIP_API_KEY: "cKTDMZAPW08dk3zl05sStzO7HRztzyn8", AGENT_NAME: "abiba", AGENT_OWNER_EMAIL: "jerome@sysloggh.com", NODE_ENV: "production", }, }, { // ── Supervisor (external watchdog) ── name: "zulip-watchdog", script: "/root/.pi/agent/extensions/zulip/watchdog.js", cwd: "/root", max_restarts: 10, min_uptime: "3s", restart_delay: 3000, kill_timeout: 5000, log_date_format: "YYYY-MM-DD HH:mm:ss Z", error_file: "/root/.pm2/logs/zulip-watchdog-error.log", out_file: "/root/.pm2/logs/zulip-watchdog-out.log", merge_logs: true, autorestart: true, watch: false, instances: 1, exec_mode: "fork", env: { NODE_ENV: "production", }, }, ], };