2.8 KiB
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://<container-ip>:8080
Files Involved
src/routes/devProxy.jssrc/app.jssrc/auth/tokens.js
Current Limitations
- browser still sees API host/IP until portal is behind a proper domain/reverse proxy
- host-based
dev-<vmid>.zlh.devrouting 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)