Skip to content

OpenClaw dashboard URL doesn't resolve — hostname-based routing needs DNS #150

@bussyjd

Description

@bussyjd

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:

  1. obolup.sh only adds 127.0.0.1 obol.stack to /etc/hosts
  2. Each OpenClaw instance creates an HTTPRoute with per-instance hostname openclaw-<id>.obol.stack
  3. These per-instance hostnames are not added to /etc/hosts
  4. 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.stack

Generated 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.stack hostname 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 sudo each 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-resolved or dnsmasq)
  • 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 dnsmasq

Option 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions