OpenClaw 대시보드가 로딩되지 않아요: 포트, WebSocket, 리버스 프록시 문제 해결

안녕하세요, 대시보드 문제 해결자 여러분 — OpenClaw의 게이트웨이가 분명히 실행 중인데도 빈 페이지, 연결 거부, 또는 "인증되지 않음" 오류를 마주하고 계신가요? 저도 그런 경험이 있습니다.

지난주에 저는 네 가지 설정에서 이 문제를 디버깅했습니다: Mac에서의 로컬 개발, Ubuntu에서의 Docker, nginx 리버스 프록시, 그리고 Tailscale로 노출된 인스턴스. 각각 다른 실패 모드를 가지고 있었지만, 모두 다섯 가지 근본 원인으로 연결되었습니다.

HTML은 로드됩니다. DevTools에서는 WebSocket 핸드셰이크 실패를 보여줍니다. 게이트웨이 로그는 유용한 정보를 주지 않습니다. 인증, 네트워킹, 또는 설정 손상인지 확실하지 않습니다.

실제로 문제를 일으키는 것은 다음과 같습니다: 프록시에서 WebSocket 업그레이드 헤더가 누락됨, Docker NAT가 localhost를 외부로 처리함, 인증 토큰이 localStorage에 저장되지 않음, 혹은 이전 Clawdbot/Moltbot 서비스가 여전히 실행 중인 포트 충돌.

이 가이드는 제가 이러한 문제를 반복적으로 해결한 후 구축한 진단 흐름을 안내합니다. 여기서 시작하여 체크를 따라가면 대시보드를 작동시키거나 정확히 어떤 문제를 보고해야 할지 알게 될 것입니다.


서비스 상태 확인

Before diving into proxies and ports, verify the gateway is actually functional.

Is the Gateway Process Running?

# Check gateway status
openclaw status
# If using systemd
systemctl --user status openclaw-gateway
# Docker users
docker ps | grep openclaw-gateway

What you're looking for:

  • Status: running or active
  • Uptime: More than 30 seconds (not crash-looping)
  • No recent restarts

If it's not running or restarting constantly, stop here and fix the gateway install issues first.

Can the WebSocket Server Respond?

Test the WebSocket endpoint directly:

# Install wscat if you don't have it
npm install -g wscat
# Test connection (replace with your actual token)
wscat -c "ws://127.0.0.1:18789/?token=YOUR_TOKEN_HERE"

Possible outcomes:

  • Connected, gets challenge message → Gateway is fine, problem is browser/proxy
  • Connection refused → Port/bind issue, go to next section
  • Connected then immediately closes with 1008 → Auth problem

If wscat connects but the browser doesn't, the issue is either CORS, proxy config, or browser security policy.

Check What the Gateway Actually Heard

Look at recent logs:

# View last 50 log lines
openclaw logs --limit 50
# Docker
docker logs openclaw-gateway --tail 50
# Look for WebSocket handshake attempts
openclaw logs | grep -E 'ws\]|websocket|handshake'

Key patterns:

  • [ws] accepted → Connection succeeded
  • [ws] closed before connect ... code=1008 reason=pairing required → Auth mismatch
  • [ws] closed before connect ... code=1008 reason=unauthorized: gateway token missing → Token not reaching gateway
  • Origin http://... is not allowed → CORS issue

Port Conflicts & Bind Addresses

Problem: Gateway Binds to Wrong Interface

Symptom: Gateway runs fine via CLI, but browser can't connect to 127.0.0.1:18789.

Cause: Gateway bound to a Tailscale IP, VPN interface, or external IP instead of loopback.

This is Issue #1380 — when Tailscale is active, the gateway sometimes binds to 100.x.x.x instead of 127.0.0.1. Browser WebSocket connections to Tailscale IPs fail.

Diagnose:

# Check what interface the gateway bound to
openclaw status
# Or inspect the actual listening socket
sudo lsof -i :18789
# Look at the "NAME" column - should show 127.0.0.1:18789

Fix:

Force loopback binding in config (~/.openclaw/config.json):

{
  "gateway": {
    "bind": "loopback",
    "port": 18789
  }
}

Valid bind options:

  • loopback → 127.0.0.1 only (default, safest)
  • lan → 0.0.0.0 (all interfaces, requires auth)
  • tailnet → Tailscale IP

After changing bind, restart:

systemctl --user restart openclaw-gateway
# or
docker compose restart openclaw-gateway

Problem: Port 18789 Already in Use

Symptom: Gateway won't start, logs show EADDRINUSE.

Cause: Old Clawdbot/Moltbot gateway still running, or another service using 18789.

Diagnose:

# Find what's using the port
sudo lsof -i :18789
# Or
sudo ss -tlnp | grep 18789

Fix Option A: Stop Conflicting Service

# Stop old Clawdbot
systemctl --user stop clawdbot-gateway
# Kill the process if needed
sudo kill -9 <PID>

Fix Option B: Change OpenClaw Port

In ~/.openclaw/config.json:

{
  "gateway": {
    "port": 18790
  }
}

Update Docker compose if using containers:

ports:
  - "127.0.0.1:18790:18790"

Then access dashboard at http://127.0.0.1:18790/.

Problem: Docker NAT Breaks Localhost Detection

Symptom: Running gateway in Docker Desktop on Windows/Mac, browser shows "pairing required" even with correct token.

Cause: Docker's NAT networking makes the gateway see connections from 172.18.0.1 instead of 127.0.0.1. Gateway treats this as an external connection requiring node pairing.

Diagnose:

Check gateway logs for:

[ws] closed before connect conn=... remote=172.18.0.1 ... code=1008 reason=pairing required

If you see remote=172.18.0.1 but you're connecting from 127.0.0.1, this is the issue.

Fix:

Add trusted proxies to your config:

{
  "gateway": {
    "trustedProxies": ["172.18.0.0/16", "172.17.0.0/16"]
  }
}

Or run gateway with --bind lan and enforce token auth:

{
  "gateway": {
    "bind": "lan",
    "auth": {
      "mode": "token",
      "token": "your-secret-token"
    }
  }
}

Better fix for Windows/Mac: Run gateway natively instead of in Docker to get real localhost connections.


Reverse Proxy WebSockets Checklist

If you're exposing OpenClaw through nginx, Caddy, or another reverse proxy, WebSocket support needs explicit configuration.

nginx Configuration

The dashboard uses WebSockets for real-time communication. Standard HTTP proxying breaks this.

Minimal working config:

server {
    listen 443 ssl;
    server_name openclaw.yourdomain.com;
    # SSL certs
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    location / {
        proxy_pass http://127.0.0.1:18789;
        # Critical for WebSockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";     
        # Pass through client info
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # WebSocket timeouts
        proxy_read_timeout 86400;
        proxy_send_timeout 86400;
    }
}

Common nginx mistakes:

  • Missing proxy_http_version 1.1 → WebSocket upgrade fails
  • Missing Upgrade and Connection headers → Handshake rejected
  • Default timeout (60s) → WebSocket closes after idle time

Detailed nginx reverse proxy guide: nginx WebSocket proxying

Caddy Configuration

Caddy handles WebSockets automatically, but you still need proper config:

openclaw.yourdomain.com {
    reverse_proxy 127.0.0.1:18789
}

That's it. Caddy auto-detects the WebSocket upgrade and adjusts timeouts.

If using subpath:

yourdomain.com {
    reverse_proxy /openclaw/* 127.0.0.1:18789
}

Then access via https://yourdomain.com/openclaw/.

Debugging Caddy WebSocket issues:

Enable verbose logging:

openclaw.yourdomain.com {
    log {
        output file /var/log/caddy/openclaw.log
        level DEBUG
    }
    reverse_proxy 127.0.0.1:18789
}

Check for websocket upgrade in logs. If missing, Caddy isn't detecting the upgrade request.

Apache Configuration

Less common but occasionally used:

<VirtualHost *:443>
    ServerName openclaw.yourdomain.com
    SSLEngine On
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem
    # Enable proxy modules
    # a2enmod proxy proxy_http proxy_wstunnel rewrite
    ProxyPreserveHost On
    # WebSocket tunnel
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)  ws://127.0.0.1:18789/$1 [P,L]
    # Regular HTTP proxy
    ProxyPass / http://127.0.0.1:18789/
    ProxyPassReverse / http://127.0.0.1:18789/
</VirtualHost>

Enable required modules:

sudo a2enmod proxy proxy_http proxy_wstunnel rewrite
sudo systemctl restart apache2

CORS / HTTPS Gotchas

Mixed Content Blocking

Symptom: Dashboard loads over HTTPS but WebSocket connection fails with mixed content error.

Cause: Browser blocks ws:// (non-secure WebSocket) when page is loaded over https://.

Fix:

Use wss:// (WebSocket Secure) behind your reverse proxy.

Your nginx/Caddy terminates SSL and forwards to http://127.0.0.1:18789, but the browser needs to connect via wss://.

Example flow:

  • Browser: wss://openclaw.yourdomain.com/ → nginx with SSL
  • nginx: ws://127.0.0.1:18789/ → gateway (local, no SSL needed)

The dashboard auto-detects this if you access it via HTTPS URL.

CORS Rejections

Symptom: Browser console shows CORS policy: No 'Access-Control-Allow-Origin' header.

Cause: Accessing dashboard from a different domain than the gateway expects.

Context: As of OpenClaw's security updates, the Control UI has stricter origin validation.

Fix:

If your dashboard is at https://openclaw.example.com but gateway config doesn't know about it:

{
  "gateway": {
    "cors": {
      "origins": ["https://openclaw.example.com"]
    }
  }
}

Security note: Don't use "origins": ["*"] in production. This exposes your gateway to external access vulnerabilities.

Token Not Persisting in localStorage

Symptom: Dashboard keeps asking for token every time you reload.

Cause: Browser's localStorage API blocked or cleared.

Diagnose:

Open DevTools → Application → Local Storage → http://127.0.0.1:18789

Look for key: openclaw-gateway-token

If missing after login, check:

  • Browser in private/incognito mode (localStorage disabled)
  • Third-party cookie blocking extensions
  • Browser set to clear storage on exit

Workaround:

Use the tokenized URL every time:

openclaw dashboard

This command outputs a URL with ?token=... appended. The UI strips it after first load and saves to localStorage — but if that fails, you need the URL each time.


Logs to Collect Before Reporting

If none of the above fixes work, you're in edge case territory. Before opening a GitHub issue, collect these logs:

Gateway Logs

# Last 100 lines with timestamps
openclaw logs --limit 100 > gateway-logs.txt
# Docker
docker logs openclaw-gateway --tail 100 > gateway-logs.txt

Browser Console Logs

  1. Open DevTools (F12)
  2. Go to Console tab
  3. Reproduce the connection failure
  4. Right-click console → Save as... → browser-console.txt

WebSocket Frame Inspection

  1. DevTools → Network tab
  2. Filter: WS
  3. Click the WebSocket connection
  4. Check "Messages" tab for handshake details
  5. Screenshot the Headers tab showing request/response

Config Sanitized

# Export config (redact tokens)
cat ~/.openclaw/config.json | sed 's/"token": ".*"/"token": "REDACTED"/g' > config-sanitized.json

Network Environment

# Check firewall rules (Linux)
sudo iptables -L -n | grep 18789
# Check what's binding to the port
sudo lsof -i :18789
# Test from external host if relevant
curl -v http://your-server-ip:18789/

What Actually Breaks Dashboards

다양한 환경에서 디버깅한 후, 다음과 같은 실패 분포를 확인했습니다:

60% - 역방향 프록시 WebSocket 구성 누락

  • Upgrade/Connection 헤더가 없는 nginx
  • 잘못된 타임아웃 설정
  • proxy_http_version 1.1 누락

20% - Docker NAT가 localhost를 외부로 인식

  • Windows/Mac Docker Desktop
  • 게이트웨이를 네이티브로 실행하거나 trustedProxies 추가로 해결

10% - 오래된 Clawdbot/Moltbot의 포트 충돌

  • OpenClaw 설치 전에 이전 서비스를 중지하는 것을 잊음
  • 이전 프로세스를 종료하거나 포트 변경으로 해결

5% - 루프백 대신 Tailscale 바인딩

  • Tailscale이 활성화되면 게이트웨이가 100.x.x.x에 바인딩됨
  • 설정에서 bind: "loopback" 강제로 해결

5% - 인증 토큰 불일치

  • 설정의 토큰이 URL의 토큰과 일치하지 않음
  • openclaw dashboard를 실행하여 올바른 토큰화된 링크로 해결

가장 흔한 문제인 역방향 프록시 WebSocket 구성은 HTTP 부분은 잘 작동하기 때문에 놓치기 쉽습니다. HTML과 CSS는 로드되지만, WebSocket은 조용히 실패합니다.

프록시 뒤에서 실행 중이고 대시보드가 연결되지 않는다면, 그것이 첫 번째로 확인해야 할 사항입니다.

Macaron에서는 UI를 호스팅해드려요 — nginx 설정 디버깅, WebSocket 타임아웃 조정, Docker NAT의 예기치 않은 문제들이 없어요. 워크플로우를 테스트하기 전에 인프라 문제 해결에 지쳤다면, 호스팅된 UI를 선호하시나요? Macaron 계정을 생성하세요.

자주 묻는 질문

질문: 대시보드 HTML은 로드되지만 아무것도 작동하지 않아요. 어디서 시작해야 하나요? DevTools → 네트워크 → WS 탭을 열어보세요. WebSocket 핸드셰이크가 실패하면, 거의 확실히 리버스 프록시 설정에 UpgradeConnection 헤더가 누락된 것입니다. 이 경우가 60%에 달합니다. 잘못된 설치를 먼저 배제하고 싶다면, 프록시 설정을 깊게 파고들기 전에 OpenClaw 설치 가이드와 대조해보세요.

질문: 토큰을 올바르게 설정했는데도 게이트웨이가 "페어링 필요"라고 표시되는 이유는 무엇인가요? remote=172.18.0.1의 로그를 확인하세요. Docker Desktop(Windows 또는 Mac)을 사용 중이라면, NAT가 게이트웨이가 외부 연결로 인식하게 만듭니다. 게이트웨이를 네이티브로 실행하거나, 설정에 trustedProxies를 추가하세요 — Docker 설정 가이드에서는 이 시나리오에 대한 정확한 네트워크 설정을 제공합니다.

Q: 페이지를 새로고침할 때마다 게이트웨이가 토큰을 계속 요청해요. 브라우저의 localStorage가 지속되지 않는 경우입니다. 보통 시크릿 모드, 강력한 개인정보 보호 확장 프로그램, 또는 '종료 시 저장소 지우기'가 활성화되어 있을 때 발생합니다. openclaw dashboard에서 토큰화된 URL을 사용하세요. 인증 문제가 이 이상으로 넘어간다면, OpenClaw 보안 체크리스트에서 토큰 관리에 대한 자세한 내용을 확인할 수 있습니다.

Q: 포트 18789가 이미 사용 중입니다. 무엇이 점유하고 있나요? 대부분의 경우 오래된 Moltbot 또는 Clawdbot 게이트웨이가 여전히 실행 중입니다. lsof -i :18789를 사용하면 무엇인지 확인할 수 있습니다. 이를 종료하거나 OpenClaw의 포트를 구성에서 변경하세요. 최근 Moltbot에서 이전했다면, 둘을 함께 실행하는 방법에 대한 글을 읽어보세요. 서비스 충돌이 흔히 발생하는 문제입니다.

Q: HTTPS 대시보드가 WebSocket에 연결할 수 없습니다. 혼합 콘텐츠 문제입니다 — 브라우저는 HTTPS 페이지에서 ws://를 허용하지 않습니다. 프록시가 wss:// 종료를 처리해야 합니다. VPS를 사용 중이고 이 문제를 계속 겪는다면, VPS 배포 가이드에서 nginx + SSL 설정을 직접 참고할 수 있습니다.

Q: Tailscale이 활성화된 후 대시보드가 로컬에서 로드되지 않아요. 알려진 문제 (#1380) — Tailscale이 127.0.0.1 대신 100.x.x.x로 게이트웨이를 가져올 수 있어요. 설정에 "bind": "loopback"을 추가하고 다시 시작하세요. 그 후에도 바인드 동작이 혼란스러우면, 게이트웨이 참조에서 모든 옵션을 명확하게 설명하고 있어요.

안녕하세요, 저는 Hanks입니다 — 워크플로우 조작자이자 AI 도구 애호가로, 자동화, SaaS 및 콘텐츠 제작 분야에서 10년 이상의 실무 경험을 가지고 있습니다. 제가 도구를 테스트하니 여러분은 그럴 필요 없습니다. 복잡한 과정을 간단하고 실행 가능한 단계로 나누고, '실제로 효과가 있는 것'의 숫자를 파헤칩니다.

지원하기 Macaron 의 첫 친구들