feat: replace PM2 with systemd --user services for production

Runs tssbot-web, tssbot-webhook, and tssbot-backend as systemd --user
units instead of PM2 processes. tssbot-web moves from a 2-worker PM2
cluster to a single instance, so deploys now restart it directly
instead of doing a zero-downtime cluster reload.

webhook.cjs now shells out to `systemctl --user restart` instead of
`pm2 reload`, and PM2_RESTART_TARGETS/WEBHOOK_PM2_NAME are renamed to
RESTART_TARGETS/WEBHOOK_SERVICE_NAME. scripts/install-systemd-services.sh
symlinks the new unit files into ~/.config/systemd/user and enables them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 22:58:15 +00:00
parent 1fee214785
commit 341dae1913
10 changed files with 172 additions and 205 deletions
+4 -4
View File
@@ -3510,10 +3510,10 @@ function shutdown() {
// server.close() only fires its callback once every socket is gone, and idle
// HTTP keep-alive sockets (held open by nginx/Cloudflare) never close on
// their own — so without this the worker hangs the full kill_timeout on every
// stop/reload, which is what wedges the PM2 cluster daemon. Close idle sockets
// immediately, let in-flight requests finish for a short grace period, then
// force the rest so shutdown completes well inside kill_timeout.
// their own — so without this the process hangs the full TimeoutStopSec on
// every stop/restart. Close idle sockets immediately, let in-flight requests
// finish for a short grace period, then force the rest so shutdown completes
// well inside TimeoutStopSec.
server.closeIdleConnections()
setTimeout(() => server.closeAllConnections(), 3000).unref()