-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Problem
The frontend "Dashboard" button for an OpenClaw instance opens http://openclaw-<id>.obol.stack/ (e.g., http://openclaw-sweeping-filly.obol.stack/). This URL never resolves because:
obolup.shonly adds127.0.0.1 obol.stackto/etc/hosts- Each OpenClaw instance creates an HTTPRoute with per-instance hostname
openclaw-<id>.obol.stack - These per-instance hostnames are not added to
/etc/hosts - The frontend constructs the URL at
OpenClawInstanceCard.tsx:118:const dashboardUrl = \`http://\${instance.namespace}.obol.stack\`; // TODO: confirm this url
The same pattern would affect any future app that uses per-instance hostname routing.
Context
How other services route
The stack uses obol.stack as the single hostname with path-based routing for infrastructure services:
/→ obol-frontend/rpc→ eRPC
Network nodes also use path-based routes on obol.stack, but these are RPC endpoints for programmatic API access (not user-facing dashboards):
/ethereum-<id>/execution→ Geth JSON-RPC (port 8545)/ethereum-<id>/beacon→ Beacon API (port 5052)/aztec-<id>/→ Aztec sequencer node RPC (port 8080)
How OpenClaw currently routes (hostname-based)
OpenClaw is different — it uses hostname-based routing via HTTPRoute because it serves a web dashboard (the Control UI), not just an API:
hostnames:
- openclaw-<id>.obol.stackGenerated in openclaw.go:202:
hostname := fmt.Sprintf("openclaw-%s.%s", id, defaultDomain)OpenClaw basePath support investigation
OpenClaw's gateway does support serving the Control UI behind a path prefix via gateway.controlUi.basePath config:
| Component | basePath support | Notes |
|---|---|---|
| Control UI (HTML/SPA) | Yes | Server injects window.__OPENCLAW_CONTROL_UI_BASE_PATH__, client-side router strips/adds prefix |
| Static assets (JS/CSS) | Yes | Vite base config + runtime injection |
| WebSocket | Partial | Uses explicit gatewayUrl, doesn't auto-derive from basePath |
HTTP API (/v1/chat/completions) |
No | Absolute paths, not prefixed with basePath |
Key limitation: The dashboard's API calls to /v1/chat/completions are absolute. Behind a path-stripping reverse proxy, these would NOT be routed to the correct OpenClaw instance.
Options
Option A: Path-based routing with basePath config
Change from http://openclaw-<id>.obol.stack/ to http://obol.stack/openclaw-<id>/.
OpenClaw supports this via gateway.controlUi.basePath — the Control UI, assets, and SPA routing all handle basePath correctly. However, the API endpoints (/v1/chat/completions) use absolute paths and would NOT be routed through the prefix.
Workaround: Add a second HTTPRoute for /v1/* per instance, or have the frontend continue proxying API calls server-side (which it already does for chat via /api/openclaw/chat).
Pros:
- Uses the single
obol.stackhostname already in/etc/hosts - No additional DNS/hosts configuration needed
Cons:
- API calls from the Control UI dashboard would break (absolute
/v1/*paths) - Requires chart changes to inject basePath into
openclaw.json - More complex HTTPRoute setup (URL rewrite + potentially dual routes)
Option B: Per-instance /etc/hosts entries
Have obol openclaw setup (or sync) add 127.0.0.1 openclaw-<id>.obol.stack to /etc/hosts.
Pros:
- No changes to routing or OpenClaw config
- Hostname-based routing works as-is
- Dashboard + API + WebSocket all work natively
Cons:
- Requires
sudoeach time an instance is created/deleted - Needs cleanup logic on
obol openclaw delete - Fragile — entries can go stale if delete doesn't run cleanly
- Doesn't scale well with many instances
Option C: Local DNS wildcard resolver
Configure *.obol.stack → 127.0.0.1 via system DNS.
Pros:
- Solves the problem for all current and future per-instance services
- Zero per-instance configuration
- Clean separation of concerns
Cons:
- Platform-specific: macOS (
/etc/resolver/+ lightweight DNS), Linux (systemd-resolvedordnsmasq) - Adds bootstrap complexity to
obolup.sh - May conflict with corporate DNS/VPN setups
macOS implementation (relatively simple):
sudo mkdir -p /etc/resolver
echo "nameserver 127.0.0.1" | sudo tee /etc/resolver/obol.stack
# + run a lightweight DNS responder or use dnsmasqOption D: Frontend proxies the dashboard (no external URL)
Don't link to the OpenClaw dashboard externally. Instead, proxy or embed it through the frontend.
Pros:
- No DNS/routing changes at all
- Server-side already has in-cluster access via K8s service URLs
- Auth token handling stays server-side
Cons:
- Significant frontend work (iframe embedding or full proxy)
- Loses the native OpenClaw dashboard experience
- WebSocket proxying adds complexity
Recommendation
Option C (wildcard DNS) is the most robust long-term solution — solves it for OpenClaw and any future per-instance service. macOS makes this relatively easy via /etc/resolver/.
Option B (per-instance hosts) is the quickest fix if we want to ship something now.
Option A (path-based) is technically possible since OpenClaw supports basePath, but the absolute API paths from the Control UI make it the most complex option.
Files involved
| File | Role |
|---|---|
obolup.sh (lines 1085-1148) |
/etc/hosts configuration |
internal/openclaw/openclaw.go:202 |
Hostname generation (openclaw-<id>.obol.stack) |
internal/openclaw/chart/templates/httproute.yaml |
HTTPRoute with hostname matching |
obol-stack-front-end/.../OpenClawInstanceCard.tsx:118 |
Dashboard URL construction |
OpenClaw src/gateway/control-ui.ts |
basePath handling for Control UI |
OpenClaw src/config/schema.ts |
gateway.controlUi.basePath config schema |