Add session summary — hosted IDE via Traefik wildcard curl-verified
This commit is contained in:
parent
c499be3e1e
commit
f1270c8ede
107
Session_Summaries/2026-03-22_Hosted-IDE-Traefik-Wildcard.md
Normal file
107
Session_Summaries/2026-03-22_Hosted-IDE-Traefik-Wildcard.md
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# 2026-03-22 – Hosted Dev IDE via Traefik Wildcard
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Long session. Explored multiple approaches to masking the raw API IP in the
|
||||||
|
IDE browser URL. Ended with the correct architecture working and curl-verified.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Decision
|
||||||
|
|
||||||
|
Rejected: Traefik direct routing to container (removes API auth boundary, insecure)
|
||||||
|
Rejected: Caddy on API host (HSTS/HTTPS issues with zerolaghub.dev domain)
|
||||||
|
Chosen: Traefik on `zlh-zpack-proxy` → API → container
|
||||||
|
|
||||||
|
This is correct because:
|
||||||
|
- Traefik already handles TLS for the platform
|
||||||
|
- API remains the auth and proxy boundary
|
||||||
|
- No per-container DNS or routing side effects needed
|
||||||
|
- Clean hostname with HTTPS without purchasing a cert
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What Was Built
|
||||||
|
|
||||||
|
### Traefik wildcard TLS
|
||||||
|
|
||||||
|
- `zpackv2` certResolver already configured with Cloudflare DNS-01 challenge
|
||||||
|
- Stale `_acme-challenge` TXT records in Cloudflare blocked initial cert issuance — deleted manually
|
||||||
|
- Wildcard cert `*.zerolaghub.dev` issued successfully via Let's Encrypt
|
||||||
|
|
||||||
|
### Traefik dynamic config
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
dev-ide:
|
||||||
|
rule: "HostRegexp(`dev-{vmid:[0-9]+}.zerolaghub.dev`)"
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
service: dev-ide-api
|
||||||
|
tls:
|
||||||
|
certResolver: zpackv2
|
||||||
|
domains:
|
||||||
|
- main: "zerolaghub.dev"
|
||||||
|
sans:
|
||||||
|
- "*.zerolaghub.dev"
|
||||||
|
services:
|
||||||
|
dev-ide-api:
|
||||||
|
loadBalancer:
|
||||||
|
passHostHeader: true
|
||||||
|
servers:
|
||||||
|
- url: "http://10.60.0.245:4000"
|
||||||
|
```
|
||||||
|
|
||||||
|
`passHostHeader: true` is critical — preserves `dev-6070.zerolaghub.dev`
|
||||||
|
through to the API so `handleHostedProxy` can extract the vmid.
|
||||||
|
|
||||||
|
### API devProxy.js
|
||||||
|
|
||||||
|
`handleHostedProxy` added — extracts vmid from `Host` header, validates
|
||||||
|
token, sets cookie, proxies to container. This was the missing piece that
|
||||||
|
caused 404s until the code was deployed.
|
||||||
|
|
||||||
|
`.env` aligned:
|
||||||
|
- `DEV_IDE_RETURN_HOSTED_URL=true`
|
||||||
|
- `DEV_IDE_HOST_SUFFIX=zerolaghub.dev`
|
||||||
|
- `DEV_IDE_PUBLIC_SCHEME=https`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Curl-Verified Response Chain
|
||||||
|
|
||||||
|
```
|
||||||
|
GET https://dev-6070.zerolaghub.dev/?token=<valid>
|
||||||
|
→ 302 + Set-Cookie: zlh_dev_ide_token
|
||||||
|
|
||||||
|
GET https://dev-6070.zerolaghub.dev/ (with cookie)
|
||||||
|
→ 302 → /?folder=/home/dev/workspace
|
||||||
|
|
||||||
|
GET https://dev-6070.zerolaghub.dev/?folder=/home/dev/workspace
|
||||||
|
→ 200 (code-server HTML)
|
||||||
|
```
|
||||||
|
|
||||||
|
Full chain confirmed: Browser → Traefik → API → container:6000
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Lessons
|
||||||
|
|
||||||
|
- ERR_CONNECTION_CLOSED from browser (but curl works) = H2 mismatch or wrong
|
||||||
|
target. In this case it was the API not running the new code (404), not H2.
|
||||||
|
- `passHostHeader: true` in Traefik is the equivalent of Caddy's
|
||||||
|
`header_up Host {host}` — without it Express resolves relative redirects
|
||||||
|
against the internal IP, leaking it to the browser.
|
||||||
|
- Wildcard certs require DNS-01 challenge — stale TXT records in Cloudflare
|
||||||
|
will block issuance silently. Check and clear them first.
|
||||||
|
- Traefik and the API are on different subnets (10.70.x vs 10.60.x) — always
|
||||||
|
verify cross-subnet reachability with curl before debugging proxy config.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Remaining
|
||||||
|
|
||||||
|
- Browser validation (curl is confirmed, browser WebSocket not yet tested)
|
||||||
|
- Portal "Open IDE" button confirmation under hosted flow
|
||||||
|
- Legacy `/__ide/:id` compatibility cleanup once browser is confirmed
|
||||||
Loading…
Reference in New Issue
Block a user