Skip to main content

WebSocket setup

Run

cd apps/web-socket
npm run dev # tsx watch, port 8080

Production:

npm run build # tsc → dist/
npm start

Environment

VariableRequiredNotes
DATABASE_URLYesSame database as apps/web
WS_AUTH_SECRETYesByte-identical to the web app's value
WS_ALLOWED_ORIGINSYesComma-separated origins
GIT_SERVICE_SECRETYesBearer token for /git
PORTNoHardcoded to 8080 in index.ts:9

:::danger The single most common failure If WS_AUTH_SECRET differs between the two apps — including a trailing newline or a stray quote — every connection is accepted at the TCP level and then immediately closed during token verification. The browser shows a connect/disconnect loop with no useful error.

Verify they match:

grep WS_AUTH_SECRET .env apps/web-socket/.env

:::

Both apps fall back to NEXTAUTH_SECRET when WS_AUTH_SECRET is unset, so setting neither works in development as long as NEXTAUTH_SECRET is shared.

Origins

# Development
WS_ALLOWED_ORIGINS=http://localhost:3000

# Production — include every origin that will connect
WS_ALLOWED_ORIGINS=https://ko-lab.app,https://www.ko-lab.app

A rejected origin logs server-side:

🚫 Rejected WS connection from unauthorized origin: https://example.com

Preview deployments each get their own origin, so a Vercel preview will fail to connect unless its URL is added.

Git workspaces

Clones are written to apps/web-socket/workspaces/. This needs:

  • Disk — one clone per group per branch, so a large repo across several branches adds up quickly
  • A writable filesystem — which rules out most serverless platforms
du -sh apps/web-socket/workspaces

Nothing prunes these automatically. On a long-running deployment, stale branch directories accumulate; clearing them is safe while no operation is in flight, since they are re-cloned on demand.

Verify

# Health
curl http://localhost:8080/health

# Origin rejection — should fail
npx wscat -c ws://localhost:8080/ws -o http://evil.example.com

# Without a token — should close immediately
npx wscat -c ws://localhost:8080/ws

Deployment notes

This service cannot run on Vercel or any serverless platform. It needs persistent connections and a writable disk. Use a long-running host — Railway, Render, Fly.io or a VPS.

Because all connection state is in-process memory, you cannot run more than one instance without users on different instances failing to see each other's messages. See Known limitations.

Troubleshooting

SymptomCause
Connect/disconnect loopWS_AUTH_SECRET mismatch
Rejected … unauthorized originOrigin not in WS_ALLOWED_ORIGINS
Connection refused after 5 tabsMAX_CONNECTIONS_PER_IP is 5
Closed while typing fast10 msg/s rate limit
Large paste dropped8 KB message cap
Git endpoints 500Check disk space and workspaces/ permissions