Overview

This map covers EVERY listening TCP port on the VPS, all 16 active user-systemd services, all 8 PM2 processes, and all 41 disabled user-systemd units (kept here for reference per Henry’s Q5 directive). Verified by 3 parallel Sonnet sub-agents on 2026-05-04 ~12:20 UTC.

At a glance: 48 listening ports · 8 PM2 procs · 16 active systemd-user services · 41 disabled systemd-user units · 1 webhook DOWN (18801 Gmail Push) · 6 drift findings.


Diagram — Live ports by exposure zone

graph TB
    classDef pub fill:#fee,stroke:#c33,color:#000
    classDef tail fill:#ddf,stroke:#33c,color:#000
    classDef loop fill:#dfd,stroke:#3c3,color:#000
    classDef pm2 fill:#fec,stroke:#c93,color:#000
    classDef down fill:#999,stroke:#600,color:#fff,stroke-dasharray: 5 5
    classDef nginx fill:#ffd,stroke:#993,color:#000

    INET[Internet]
    CF[Cloudflare Tunnel<br/>webhook.reri.co]
    TS[Tailscale Tailnet<br/>100.85.89.1]

    subgraph webhooks_pub["Public Webhook Handlers (Cloudflare-fronted)"]
        P18790["**:18790** hubspot-handler<br/>PM2: hubspot"]:::pm2
        P18793["**:18793** salesmessage-handler<br/>PM2: salesmsg"]:::pm2
        P18797["**:18797** twilio-voice-handler<br/>PM2: twilio"]:::pm2
        P18792["**:18792** quo-handler-enhanced<br/>systemd: openphone-webhook"]:::loop
        P18801["**:18801** gmail-push-handler<br/>NOT RUNNING — provider unwired"]:::down
    end

    subgraph webhooks_tail["Tailscale-only Handlers"]
        P18802["**:18802** imessage-handler<br/>systemd: imessage-webhook"]:::tail
    end

    subgraph core["OpenClaw Core (loopback)"]
        P18789["**:18789** openclaw-gateway<br/>Go binary"]:::loop
        P18791["**:18791** gateway Quo dispatch<br/>same Go binary"]:::loop
        P18795["**:18795** api-proxy<br/>internal proxy-server.js"]:::loop
        P18798["**:18798** quo-mention-receiver<br/>Aurora WS trigger"]:::loop
        P18820["**:18820** hubspot-webhook-bridge<br/>NOT 'Atlas dormant'"]:::loop
    end

    subgraph llm["LLM Dispatch (loopback)"]
        P18900["**:18900** portkey-proxy<br/>per-agent cost attribution"]:::loop
        P18903["**:18903** anthropic-max-router<br/>teamsteph Max plan ⚠ wildcard bind"]:::pub
        P18910["**:18910** claude-max-api-proxy<br/>teamsteph"]:::loop
        P18911["**:18911** RESERVED<br/>henryRERI Max plan"]:::down
    end

    subgraph wildcard["Wildcard-public (no CF, no FUNNEL)"]
        P18794["**:18794** discord-lovable-bridge<br/>PM2 ⚠"]:::pm2
        P18796["**:18796** salesmsg-openclaw-gateway<br/>internal SMS gateway ⚠"]:::pub
        P18799["**:18799** lovable-api-server<br/>PM2 ⚠"]:::pm2
        P18812["**:18812** broadcast-audit<br/>response audit UI ⚠"]:::pub
        P3001["**:3001** openphone-webhook-receiver<br/>workspace-dispo fork ⚠"]:::pub
        P3100["**:3100** ops-dashboard<br/>static serve"]:::pub
        P8080["**:8080** code-server@opsadmin<br/>VSCode in browser"]:::pub
    end

    subgraph nginx_zone["nginx-fronted"]
        P80["**:80** nginx HTTP redirect"]:::nginx
        P443ts["**:443** tailscaled TLS<br/>Tailscale-only"]:::tail
        P8443["**:8443** nginx upstream"]:::nginx
        P8444["**:8444** nginx upstream alt"]:::nginx
        P18804["**:18804** nginx fronts :18803<br/>RERI Dispo Model"]:::nginx
        P18810["**:18810** nginx alt vhost ⚠ 500"]:::nginx
        P18803["**:18803** reri-dispo-model<br/>landing page"]:::loop
    end

    subgraph aurora_internal["Aurora internal services"]
        P3847["**:3847** aurora-webhook<br/>NOT 'IL gateway 3848'"]:::loop
        P8890["**:8890** aurora-dashboard"]:::loop
        P8891["**:8891** deals-api"]:::loop
    end

    subgraph infra["Infra / Observability (loopback)"]
        P6379["**:6379** redis"]:::loop
        P19999["**:19999** netdata UI"]:::loop
        P20241["**:20241** cloudflared control"]:::loop
        P4317["**:4317** otel-plugin gRPC"]:::loop
        P8125["**:8125** netdata StatsD"]:::loop
        P53["**:53** systemd-resolved"]:::loop
        P9050["**:9050** tor SOCKS<br/>retire candidate"]:::loop
        P65529["**:65529** monarx-agent<br/>Hostinger security"]:::loop
        P631["**:631** cupsd<br/>retire candidate"]:::pub
        P22["**:22** sshd<br/>Tailscale-fronted"]:::pub
    end

    subgraph open_webui["UI services"]
        P3000["**:3000** open-webui<br/>Tailscale-only"]:::tail
    end

    INET --> CF
    INET --> TS

    CF -->|HMAC v1| P18790
    CF -->|HMAC v1| P18792
    CF -->|"?secret query token"| P18793
    CF -->|HMAC-SHA1| P18797
    CF -.->|"DOWN — 502s"| P18801

    TS -->|query token| P18802
    TS --> P3000
    TS --> P443ts
    TS --> P22

    P18790 --> P18789
    P18792 --> P18789
    P18793 --> P18789
    P18797 --> P18789
    P18802 --> P18789
    P18789 --> P18900
    P18900 -->|virtual-key per agent| AN[Anthropic / OpenAI / Moonshot]
    P18900 -.->|local shortcut| P18903
    P18789 --> P18791
    P18900 --- P6379

    P80 --> P18804
    P18804 --> P18803

Read this when: troubleshooting webhook connectivity, adding a new service per G-SERVICE-PRE-START-DOC, or verifying which handlers are CF-fronted vs loopback-only.


Live port inventory (48 ports — verified 2026-05-04)

Public webhook handlers (CF Tunnel-fronted)

PortPIDUserProcessManagerHealthNotes
187901926opsadminhubspot-handler.jsPM2 id=3200HubSpot + DocuSign + Make + OAuth callback
187924072opsadminquo-handler-enhanced.jssystemd-user openphone-webhook200OpenPhone/Quo SMS + calls
187931918opsadminsalesmessage-handler-v4-complete.jsPM2 id=2200SalesMsg (query-token auth, NOT HMAC)
187971909opsadmintwilio-voice-handler.jsPM2 id=1200Twilio voice + SMS (HMAC-SHA1 dual-host)
18801gmail-push-handler.js(none — DOWN)000🚨 NOT RUNNING — provider unwired
188022328opsadminimessage-handler.jssystemd-user imessage-webhook200BlueBubbles, Tailscale-only

OpenClaw core (loopback)

PortPIDUserProcessManagerHealthNotes
187893514opsadminopenclaw-gateway (Go)systemd-user openclaw-gatewayTCPCentral LLM dispatch
187913514opsadminopenclaw-gateway (same)systemd-user openclaw-gateway401Internal Quo dispatch
18795979opsadminapi-proxy/proxy-server.jssystemd-system openclaw-api-proxy200Internal API proxy
187982347opsadminquo-mention-receiver.jssystemd-user quo-mention-receiver200Aurora Quo trigger
18820971opsadminhubspot-webhook-bridge.jssystemd-system hubspot-webhook-bridge200⚠ NOT “Atlas dormant” — CLAUDE.md drift

LLM dispatch

PortPIDUserProcessManagerHealthNotes
189002340opsadminportkey-proxy/proxy.jssystemd-user portkey-proxy200Per-agent cost attribution
189032272opsadminanthropic-max-routersystemd-user anthropic-max-router200⚠ binds wildcard, registry says loopback
189102305opsadminclaude-max-api-proxysystemd-user claude-max-api-proxy@teamsteph200teamsteph Max plan
18911reservedReserved for henryRERI Max plan

Wildcard-public (no CF, no FUNNEL — ⚠ governance gaps)

PortPIDUserProcessManagerHealthNotes
18794964opsadmindiscord-lovable-bridge.jsPM2 id=7200 (no /health)⚠ wildcard bind, no FUNNEL entry
187969377opsadminsalesmsg-openclaw-gateway.jssystemd-system salesmsg-gateway200⚠ internal SMS gateway, wildcard
187991904opsadminlovable-api-server.jsPM2 id=0200⚠ wildcard bind
188122277opsadminbroadcast-audit-server.jssystemd-user broadcast-audit404⚠ wildcard bind
3001980opsadminworkspace-dispo/openphone-webhook-receiver.jssystemd-system openphone-dispo-webhook?200⚠ duplicate openphone path?
31002309opsadminserve -s dist -l 3100systemd-user ops-dashboard200static UI
80801911opsadmincode-serversystemd-system code-server@opsadmin401⚠ wildcard bind

nginx-fronted

PortPIDUserProcessManagerHealthNotes
801036+www-datanginxsystemd-system401HTTP entry
443998roottailscaledsystemd-systemTCPTailscale TLS
84431036+www-datanginxsystemd-system400upstream
84441036+www-datanginxsystemd-system404upstream alt
188032345opsadminreri-dispo-model/server.jssystemd-user reri-dispo-page200Behind nginx :18804
188041036+www-datanginx fronts :18803systemd-system200RERI Dispo Model
188101036+www-datanginx alt vhostsystemd-system500⚠ misconfigured upstream

Aurora internal

PortPIDUserProcessManagerHealthNotes
3847956opsadminaurora webhook-server.jssystemd-system aurora-webhook200⚠ CLAUDE.md says 3848 IL gateway — WRONG
8890955opsadmindashboard-server.pysystemd-system aurora-dashboard404Python dashboard
8891963opsadminapi-server.jssystemd-system deals-api404deals API

Infra / observability (loopback)

PortPIDUserProcessManagerNotes
221030rootsshdsystemdTailscale-fronted
53887systemd-resolvesystemd-resolvedsystemdDNS
6312578rootcupsdsystemd⚠ retire candidate (215 MB)
43173762netdataotel-pluginsystemdOpenTelemetry gRPC
6379984redisredis-serversystemdCache
8125976netdatanetdata StatsDsystemdMetrics
90501094debian-tortor SOCKSsystemd⚠ retire candidate (101 MB)
19999976netdatanetdata UIsystemdLoopback HTTP
20241959rootcloudflared controlsystemdTunnel control plane
655291009rootmonarx-agentsystemdHostinger security agent

UI

PortPIDUserProcessManagerNotes
30002293opsadminopen-webuisystemd-user openwebuiTailscale-only

Ephemeral (VSCode Remote-SSH session)

PortProcessNotes
5174playwright-mcp (npx session)ephemeral
41255 / 50408 / 60704VSCode extension host childrenephemeral
46043VSCode command-shellephemeral
58306 / 63551tailscaled control + IPv6infra-internal

All 41 disabled user-systemd units (Q5 — for reference)

Bucket A — Enable now (6 — drift / governance gaps)

UnitExecStart (≤80)Bucket reason
regen-plan-index + .timertools/regen-plan-index.shG-PLAN-INDEX-REQUIRED governance gap
tool-calls-health-check.timerscripts/tool-calls-health-check.jsPOSTGRES-CHOKEPOINT-1 / G-DRIFT-LIVE gap
omni-contact-resolver.timerscripts/workers/contact-resolver.jsPipeline gap (linker runs, resolver doesn’t)
gmail-attachment-sync.timerscripts/gmail-attachment-sync.jsDaily 03:00 PDF→HubSpot sync never fires
deal-outreach-auto-approverscripts/workers/deal-outreach-auto-approver.jsService disabled, timer firing every 10 min — paperwork drift
omni-conversation-linkerscripts/workers/conversation-linker.jsSame — service disabled, timer firing hourly

Bucket B — Keep disabled (timer-driven oneshots) (22)

acquisitions-perplexity-intel, atlas-perplexity-intel, audit-weekly-triage, coordinate-plans-heartbeat, dispo-perplexity-intel, email-deal-intake, email-signal-stage-updater ⚠ (--dry-run baked in), escrow-deadline-reminder, gmail-email-harvest, gmail-label-worker, investorlift-cookie-refresh, master-env-backup, openclaw-vault-pull, openclaw-vault-sync, osil-outcome-refresh, osil-reflexion-runner, osil-trajectory-capture, perplexity-daily-summary, perplexity-intel-cleanup, perplexity-kb-refresh, research-perplexity-intel, vendor-audit-url-verify, vendor-audit-weekly.

All timers active and firing today. Cosmetic-only enable pass would make systemctl is-enabled honest.

Bucket C — Keep disabled (manual on-demand) (6)

UnitBlocked on
bettertrading-daemon (port 18798 conflict?)”Activate BetterTrading stack” decision
bettertrading-dashboard ⚠ no package.json at WorkingDir rootSame
dispo-email-ui (port 18798)TC ops on-demand
dispo-template-watcherAirtable→SalesMsg workflow validation
investorlift-gateway (port 3848 if enabled)Phase 1.5 confirms IL SSH-to-Mac is the active pattern
prediction-ingestor”Activate BetterTrading stack”

Bucket D — Retire candidates (7)

UnitWhy retire
betterfiles-chatZero history, plan refs are April migration audits only
code-server (port 8080)VS Code Remote-SSH is the active dev pattern
ollama-bridgePlan ref is ARCHIVED; superseded by Portkey routing
openphone-dispo-webhook (port 3001)Workspace-dispo fork; conflicts with active port-18792 handler
property-view-watcherOnly plan ref is in _archived/
systemd-tmpfiles-setupSystem-scope unit miscreated in user scope
trigger-dev-workernpx trigger.dev@latest dev mode = version drift risk

⚠ Drift findings (CLAUDE.md vs live)

#CLAUDE.md / registry saysLive stateSeverity
D13848 → InvestorLift Gateway → investorlift-gateway-server.jsPort 3847 is aurora-webhook.service (webhook-server.js); IL gateway is in Bucket C disabledHIGH — wrong port AND wrong process
D218820 → Atlas iMessage bridge — dormant 2+ monthsLive PID 971 is hubspot-webhook-bridge.js (HubSpot bridge, not Atlas)HIGH — wrong attribution
D318790 → systemd hubspot-webhook.serviceLive manager is PM2 id=3 (matches FUNNEL-REGISTRY, conflicts CLAUDE.md)MEDIUM — manager mislabel
D4port-registry.md says 18903 loopback-onlyLive binds wildcard (0.0.0.0+IPv6)MEDIUM — security gap (Max router exposed)
D5FUNNEL-REGISTRY /webhook/gmail-push approved-pending-hardenHandler DOWN; provider unwired; status staleHIGH — silent failure path
D6nginx :18810 expected to serve contentReturns 500LOW — broken vhost
D7port-registry.md OpenPhone webhook (one entry)TWO live processes: openphone-webhook.service (user, :18792, canonical) + openphone-webhook system unit (:3001, workspace-dispo fork)MEDIUM — duplicate naming
D8CLAUDE.md port map = 9 rows48 live portsKNOWN — port-registry.md (Phase 1.5) is the canonical replacement; CLAUDE.md row count remains intentionally condensed

Drift fixes (proposed — no edits made)

Each is a one-line registry / map change, not a service action. Awaiting Henry approval per action gate.

  1. D1 fix — CLAUDE.md port-map: change 3848 | InvestorLift Gateway3847 | Aurora Webhook (webhook-server.js). Add (InvestorLift Gateway disabled — see Bucket C) note.
  2. D2 fix — CLAUDE.md port-map: change 18820 | Atlas iMessage bridge18820 | HubSpot Webhook Bridge (hubspot-webhook-bridge.js).
  3. D3 fix — CLAUDE.md port-map: change 18790 → systemd hubspot-webhook.service18790 → PM2 (hubspot).
  4. D4 fix — Investigate why anthropic-max-router binds wildcard; either restrict to loopback or update port-registry.md to acknowledge (and add firewall rule).
  5. D5 fix — FUNNEL-REGISTRY: change Gmail Push status to pending-provider-config until GCP setup completes (per Q4-revised). Or remove if Henry picks B-pivot.
  6. D6 fix — Investigate nginx vhost for :18810 — may be a stale upstream pointing to a dead service.
  7. D7 fix — port-registry.md: add explicit row for the workspace-dispo openphone receiver at :3001; flag as Bucket D retire-candidate.