[object Object]

← back to Homesonspec

pm2(homesonspec): node-direct next start so pm2 owns the port-holder PID (TK-10499)

7d5c17e690c4ea1aa00720a3403eaf77c34e07fc · 2026-08-27 10:23:25 -0700 · Steve

Convert homesonspec-web/admin from 'pnpm --filter ... start' (pm2 owns the
wrapper; orphaned next-server squats the port -> restart EADDRINUSE-crash-loops,
TK-10001 / usre 186519x) to node-direct 'next start -p <port>' in BOTH the
committed ecosystem.config.js and the authoritative deploy-kamatera.sh. Also
correct ecosystem ports 3100/3101 -> real prod 9975/9976. Local source only;
Kamatera re-register is drafted+gated (pending-approval/TK-10499-*).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 7d5c17e690c4ea1aa00720a3403eaf77c34e07fc
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Aug 27 10:23:25 2026 -0700

    pm2(homesonspec): node-direct next start so pm2 owns the port-holder PID (TK-10499)
    
    Convert homesonspec-web/admin from 'pnpm --filter ... start' (pm2 owns the
    wrapper; orphaned next-server squats the port -> restart EADDRINUSE-crash-loops,
    TK-10001 / usre 186519x) to node-direct 'next start -p <port>' in BOTH the
    committed ecosystem.config.js and the authoritative deploy-kamatera.sh. Also
    correct ecosystem ports 3100/3101 -> real prod 9975/9976. Local source only;
    Kamatera re-register is drafted+gated (pending-approval/TK-10499-*).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 deploy-kamatera.sh  |  9 +++++++--
 ecosystem.config.js | 30 ++++++++++++++++++++++--------
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/deploy-kamatera.sh b/deploy-kamatera.sh
index 03b03e3a..b36d4dc7 100755
--- a/deploy-kamatera.sh
+++ b/deploy-kamatera.sh
@@ -82,8 +82,13 @@ pm2 delete homesonspec-web homesonspec-admin homesonspec-workers 2>/dev/null ||
 # Free the ports from any ORPHANED next-server not managed by pm2 (a stale process squatting
 # on :$WEB_PORT/:$ADMIN_PORT makes 'next start' EADDRINUSE-crash-loop forever — TK-10001 incident).
 for P in $WEB_PORT $ADMIN_PORT; do fuser -k \$P/tcp 2>/dev/null || true; done; sleep 2
-PORT=$WEB_PORT   pm2 start 'pnpm --filter @homesonspec/web start'   --name homesonspec-web   --time
-PORT=$ADMIN_PORT pm2 start 'pnpm --filter @homesonspec/admin start' --name homesonspec-admin --time
+# node-direct start: pm2 must own the REAL next-server port-holder PID, not a pnpm/sh
+# wrapper. With the wrapper, a pm2 restart signals the wrapper while the orphaned
+# next-server keeps squatting the port -> the respawn EADDRINUSE-crash-loops (TK-10001 /
+# usre 186519x). `next start -p <port>` binds the port itself, so pm2 restart frees it
+# cleanly and the deploy-time fuser -k stops being load-bearing. TK-10499.
+PORT=$WEB_PORT   pm2 start apps/web/node_modules/.bin/next   --name homesonspec-web   --time --cwd $REMOTE/apps/web   -- start -p $WEB_PORT
+PORT=$ADMIN_PORT pm2 start apps/admin/node_modules/.bin/next --name homesonspec-admin --time --cwd $REMOTE/apps/admin -- start -p $ADMIN_PORT
 cd $REMOTE/apps/workers; pm2 start src/index.ts --name homesonspec-workers --interpreter node --interpreter-args='--env-file=$REMOTE/.env --import tsx' --time
 pm2 save; sleep 8
 echo -n '  web  '; curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:$WEB_PORT/
diff --git a/ecosystem.config.js b/ecosystem.config.js
index 7de9e25d..c1f2d981 100644
--- a/ecosystem.config.js
+++ b/ecosystem.config.js
@@ -2,18 +2,32 @@
 module.exports = {
   apps: [
     {
+      // node-direct so pm2 owns the real next-server port-holder PID (NOT a pnpm/sh
+      // wrapper). Launching via `pnpm --filter ... start` made pm2 own the wrapper;
+      // on crash/restart the orphaned next-server kept squatting :9975 and the
+      // respawn's `next start` EADDRINUSE-crash-looped forever (TK-10001 / usre
+      // 186519x, TK-10496 be669fc). `next start -p <port>` binds the port itself so
+      // `pm2 restart` cleanly frees it. Port 9975/9976 are the REAL prod ports the
+      // nginx vhost proxies to (was mislabeled 3100/3101 here — deploy-kamatera.sh
+      // is authoritative). TK-10499.
       name: "homesonspec-web",
-      cwd: __dirname,
-      script: "pnpm",
-      args: "--filter @homesonspec/web start",
-      env: { NODE_ENV: "production", PORT: "3100" },
+      cwd: __dirname + "/apps/web",
+      script: "node_modules/.bin/next",
+      args: "start -p 9975",
+      exec_mode: "fork",
+      instances: 1,
+      autorestart: true,
+      env: { NODE_ENV: "production", PORT: "9975" },
     },
     {
       name: "homesonspec-admin",
-      cwd: __dirname,
-      script: "pnpm",
-      args: "--filter @homesonspec/admin start",
-      env: { NODE_ENV: "production", PORT: "3101" },
+      cwd: __dirname + "/apps/admin",
+      script: "node_modules/.bin/next",
+      args: "start -p 9976",
+      exec_mode: "fork",
+      instances: 1,
+      autorestart: true,
+      env: { NODE_ENV: "production", PORT: "9976" },
     },
     {
       // tsx-run daemon (pg-boss queue consumer). Unlike the Next apps it does

← 7312ce4b docs(homesonspec): STEP 1 APPLIED on prod — record actual me  ·  back to Homesonspec  ·  snapshot store: store storagePath relative + resolver for vo 0a7e6b34 →