# 2026-03-21 – Dev IDE proxy working end-to-end ## Summary After significant debugging, the browser IDE is fully working through the API proxy. This was a non-trivial integration involving multiple interacting issues that had to be resolved in sequence. --- ## What Was Fixed ### 1. Token bootstrap — fixed new-tab auth loss Direct tab navigation loses `Authorization: Bearer` headers. Solution: `POST /api/dev/:id/ide-token` returns a signed token. Bootstrap route `GET /api/dev/:id/ide?token=...` validates it, sets an HTTP-only IDE cookie, then redirects into the live tunnel. ### 2. Bootstrap vs live traffic separation Routing all traffic through `/api/dev/:id/ide` caused interference with normal API route behavior. Solution: split into two paths: - bootstrap: `/api/dev/:id/ide` - live tunnel: `/__ide/:id/*` ### 3. Correct upstream port Original assumption was `6000`. Chrome blocks port 6000 as unsafe. Agent was updated to expose code-server on `8080`. API proxy updated to target `8080`. ### 4. Host header code-server expects the browser-facing host preserved through the proxy. Changed `Host` header from container host to `req.headers.host` (browser host). Matches official code-server reverse-proxy guidance. ### 5. Origin override removed Forcing `Origin` to backend target conflicted with browser-facing `Host`. Changed to pass browser `Origin` through only when present. ### 6. WS target fallback bug — the main fix HTTP requests were correctly targeting the container. WS requests were falling back to `127.0.0.1:8080`. Logs confirmed: `ECONNREFUSED 127.0.0.1:8080` Root cause: shared proxy WS handling was losing per-request target context. Fix: disabled WS on the shared `/__ide` HTTP proxy. Handled WebSocket upgrades only in `attachDevProxyServer(server)`. Built a target-bound WS proxy instance at upgrade time using the resolved container target. That eliminated the localhost fallback entirely. --- ## Working Flow ``` 1. frontend → POST /api/dev/:id/ide-token 2. API returns /api/dev/:id/ide?token=... 3. frontend opens URL in new tab 4. bootstrap validates token, sets IDE cookie, redirects to /__ide/:id/ 5. live traffic proxied through /__ide/:id/* 6. API proxies HTTP + WS to http://:8080 ``` --- ## Files Involved - `src/routes/devProxy.js` - `src/app.js` - `src/auth/tokens.js` --- ## Current Limitations - browser still sees API host/IP until portal is behind a proper domain/reverse proxy - host-based `dev-.zlh.dev` routing started but reverted — bootstrap path is canonical - service workers require HTTPS — extensions may not fully load until portal is behind SSL --- ## Next - Portal "Open IDE" button implementation - Portal behind HTTPS/domain (unblocks service workers and extension loading) - Headscale/Tailscale for local dev access (SSH, VS Code Remote)