Skip to content

Deploy Applications

This guide covers deploying the Astradial web applications and services running on the cloud VPS (89.116.31.109).

Pre-deployment checklist

  1. Verify the current service is running and note the port
  2. Check nginx config for the expected upstream port
  3. Build before restarting — never restart with a broken build
  4. Always set the correct PORT environment variable

Services Overview

Service Path on VPS Port Nginx Domain Process Manager
AstraPBX API /opt/AstraPBX 8000 devpbx.astradial.com PM2 (astrapbx, id 113)
Flow Editor /opt/pipecat-flow-editor 3001 editor.astradial.com PM2 (editor, id 88)
Pipecat Gateway /opt/pipecat-flow 7860 gateway.astradial.com systemd (pipecat-flow.service)
Workflow Engine /opt/workflow-engine 3002 (proxied via editor) PM2 (workflow-engine, id 109)

All Node services are PM2-managed

Earlier versions of this doc claimed Editor and Workflow Engine were started via nohup. They are not — both are PM2 apps. Do not use pkill -f ... && nohup node ...: PM2 auto-respawns the killed process, then your nohup attempt collides on the same port and dies with EADDRINUSE. The service still ends up running (because PM2 respawned it), but you'll see misleading errors in /tmp/editor.log / /tmp/workflow.log that don't reflect reality.

Use pm2 restart <name> instead. Trust pm2 status and pm2 logs <name> over /tmp/*.log.


Flow Editor (Next.js)

The editor has no git repository on the VPS. Deploy by copying files via scp.

Step 1: Copy changed files

# Copy specific changed files (preferred — faster)
scp "app/dashboard/[orgId]/workflows/[workflowId]/page.tsx" \
  root@89.116.31.109:"/opt/pipecat-flow-editor/app/dashboard/[orgId]/workflows/[workflowId]/page.tsx"

# Or sync the entire project (slower, full deploy)
rsync -avz --exclude node_modules --exclude .next --exclude .git \
  ./ root@89.116.31.109:/opt/pipecat-flow-editor/

Step 2: Build on VPS

ssh root@89.116.31.109 "cd /opt/pipecat-flow-editor && npm run build"

Do NOT restart before build succeeds

If the build fails, the current running version stays up. Only proceed to Step 3 after a successful build.

PM2 may auto-respawn during/after the build

Because the editor runs under PM2, simply replacing files in .next/ can trigger PM2 to detect the file changes and respawn before you explicitly restart. This is usually fine — the next request will be served from the new build — but it also means a pm2 restart in Step 3 is still required to guarantee a clean cold-start with the freshly-built .next/ directory loaded from scratch.

Step 3: Restart via PM2

ssh root@89.116.31.109 "pm2 restart editor"

PM2 will gracefully stop the running next-server, start a new one with the same PORT=3001 env (set in pm2 save'd config), and report online status within 1–3 seconds.

Step 4: Verify

# PM2 status should show "online" with restart count incremented
ssh root@89.116.31.109 "pm2 status editor"

# PM2 logs (NOT /tmp/editor.log — that file is stale, see warning above)
ssh root@89.116.31.109 "pm2 logs editor --lines 20 --nostream"

# Expected output (last few lines):
# ▲ Next.js 16.x
# - Local: http://localhost:3001
# ✓ Ready in XXXms

# Quick health check
curl -sI https://editor.astradial.com | head -3

If you ever need to start the editor from scratch

PORT=3001 pm2 start npm --name editor -- start (then pm2 save). The PORT=3001 is critical — nginx proxies to that port, and Next.js otherwise defaults to 3000.


AstraPBX API (Node.js)

Managed by PM2 — deployment is simpler.

# Pull latest changes (has git)
ssh root@89.116.31.109 "cd /opt/AstraPBX && git pull origin main"

# Restart via PM2
ssh root@89.116.31.109 "pm2 restart astrapbx"

# Check status
ssh root@89.116.31.109 "pm2 logs astrapbx --lines 10"

Workflow Engine (Node.js)

Managed by PM2 (workflow-engine, id 109). No build step — restart picks up the new file from disk.

# 1. Backup the live file (the VPS may have local edits not in git)
ssh root@89.116.31.109 "cp /opt/workflow-engine/src/server.js \
  /opt/workflow-engine/src/server.js.backup-$(date +%Y%m%d-%H%M%S)"

# 2. Diff before overwriting
scp root@89.116.31.109:/opt/workflow-engine/src/server.js /tmp/remote-server.js
diff -u /tmp/remote-server.js src/server.js   # eyeball for unexpected divergence

# 3. Copy changed files
scp src/server.js root@89.116.31.109:/opt/workflow-engine/src/server.js

# Or sync all (still avoid node_modules)
rsync -avz --exclude node_modules ./ root@89.116.31.109:/opt/workflow-engine/

# 4. Restart via PM2
ssh root@89.116.31.109 "pm2 restart workflow-engine"

# 5. Verify
ssh root@89.116.31.109 "pm2 status workflow-engine"
ssh root@89.116.31.109 "pm2 logs workflow-engine --lines 20 --nostream"

# Quick endpoint check (no /health route — use any known endpoint)
ssh root@89.116.31.109 "curl -sI http://localhost:3002/orgs/test/scheduled-jobs -o /dev/null -w 'HTTP %{http_code}\n'"

Do NOT use pkill + nohup

pkill -f 'node.*workflow' kills PM2's running child, and PM2 immediately respawns it from disk. Your follow-up nohup node src/server.js … then collides on port 3002 and dies with EADDRINUSE — but the service is still running because PM2's respawn won. The error in /tmp/workflow.log from your dead nohup attempt is misleading. Use pm2 restart workflow-engine and trust pm2 logs.

Bull jobs survive a restart

The recoverScheduledJobs() function (in src/server.js) checks for any pending/queued scheduled_jobs rows on startup. Bull data lives in Redis and persists across restarts independently — restarting workflow-engine does NOT drop scheduled jobs. The recovery function only re-enqueues rows whose Bull job has gone missing. The ✅ Recovered N scheduled jobs log line reports the SQL row count, not how many were actually re-enqueued, so seeing Recovered 0 does not mean jobs were lost.


Pipecat Gateway (Python)

# Pull latest
ssh root@89.116.31.109 "cd /opt/pipecat-flow && git pull origin main"

# Restart via systemd
ssh root@89.116.31.109 "systemctl restart pipecat-gateway"

# Check status
ssh root@89.116.31.109 "systemctl status pipecat-gateway"

Nginx Configuration

All nginx configs are in /etc/nginx/sites-enabled/:

File Upstream
editor.astradial.com 127.0.0.1:3001 (Next.js) + API proxies
devpbx.astradial.com 127.0.0.1:8000 (AstraPBX)
gateway.astradial.com 127.0.0.1:7860 (Pipecat)

The editor nginx config also proxies:

  • /api/pbx/*127.0.0.1:8000 (AstraPBX API)
  • /api/gateway/*127.0.0.1:7860 (Pipecat Gateway)
  • /api/workflow/*127.0.0.1:3002 (Workflow Engine)

After editing nginx configs:

# Test config syntax
nginx -t

# Reload (no downtime)
systemctl reload nginx

Rollback

There are two rollback paths depending on what broke.

Option A — Restore individual files from .backup-* snapshots

If you followed the "backup before scp" rule (.backup-YYYYMMDD-HHMMSS next to each overwritten file), restore in place:

# Workflow Engine — single file restore
ssh root@89.116.31.109 "cp /opt/workflow-engine/src/server.js.backup-<timestamp> \
  /opt/workflow-engine/src/server.js && pm2 restart workflow-engine"

# Editor — restore the changed files, then rebuild + restart
ssh root@89.116.31.109 "cp /opt/pipecat-flow-editor/lib/workflow/client.ts.backup-<timestamp> \
  /opt/pipecat-flow-editor/lib/workflow/client.ts"
ssh root@89.116.31.109 "cd /opt/pipecat-flow-editor && npm run build && pm2 restart editor"

Option B — Redeploy the last known-good commit from local

# On your local machine:
git checkout <last-good-commit>
rsync -avz --exclude node_modules --exclude .next --exclude .git \
  ./ root@89.116.31.109:/opt/pipecat-flow-editor/

# Then rebuild and restart on VPS
ssh root@89.116.31.109 "cd /opt/pipecat-flow-editor && npm run build && pm2 restart editor"

VPS may have files not in git

Both pipecat-flow-editor and workflow-engine have a history of local edits on the VPS that never made it back to git. Always diff between local and remote before any rsync, and prefer Option A (file-level restore) when possible.