원격 접근 (SSH, 터널, Tailnet)

이 저장소는 전용 호스트(데스크톱/서버)에서 단일 게이트웨이(마스터)를 실행하고 클라이언트를 연결하는 “SSH를 통한 원격” 접근을 지원합니다.

  • 운영자 (본인 / macOS 앱): SSH 터널링이 범용 대안입니다.
  • 노드 (iOS/Android 및 향후 디바이스): 필요에 따라 LAN/Tailnet 또는 SSH 터널을 통해 게이트웨이 WebSocket에 연결합니다.

핵심 개념

  • 게이트웨이 WebSocket은 설정된 포트(기본값 18789)의 루프백에 바인딩됩니다.
  • 원격 사용 시, 해당 루프백 포트를 SSH로 포워딩합니다 (또는 Tailnet/VPN을 사용하면 터널이 덜 필요합니다).

일반적인 VPN/Tailnet 구성 (에이전트가 실행되는 곳)

게이트웨이 호스트를 “에이전트가 실행되는 곳”으로 생각하세요. 세션, 인증 프로필, 채널, 상태를 관리합니다. 노트북/데스크톱(및 노드)이 해당 호스트에 연결합니다.

1) Tailnet 내 항상 켜진 게이트웨이 (VPS 또는 홈 서버)

영구 호스트에서 게이트웨이를 실행하고 Tailscale 또는 SSH를 통해 접근합니다.

  • 최상의 UX: gateway.bind: "loopback"을 유지하고 Control UI에 Tailscale Serve를 사용합니다.
  • 대안: 루프백 + 접근이 필요한 모든 머신에서 SSH 터널 사용.
  • 예시: exe.dev (간편한 VM) 또는 Hetzner (프로덕션 VPS).

노트북이 자주 슬립 모드에 들어가지만 에이전트는 항상 켜두고 싶을 때 적합합니다.

2) 홈 데스크톱에서 게이트웨이 실행, 노트북은 리모컨

노트북에서 에이전트를 실행하지 않습니다. 원격으로 연결합니다:

  • macOS 앱의 원격 SSH 모드 (설정 → 일반 → “OpenClaw 실행 위치”)를 사용합니다.
  • 앱이 터널을 열고 관리하므로, WebChat + 상태 확인이 바로 작동합니다.

실행 가이드: macOS 원격 접근.

3) 노트북에서 게이트웨이 실행, 다른 머신에서 원격 접근

게이트웨이를 로컬에 유지하되 안전하게 노출합니다:

  • 다른 머신에서 노트북으로 SSH 터널을 사용하거나,
  • Tailscale Serve로 Control UI를 제공하고 게이트웨이는 루프백으로 유지합니다.

가이드: Tailscale웹 개요.

명령 흐름 (어디서 무엇이 실행되는지)

하나의 게이트웨이 서비스가 상태 + 채널을 관리합니다. 노드는 주변 장치입니다.

흐름 예시 (Telegram → 노드):

  • Telegram 메시지가 게이트웨이에 도착합니다.
  • 게이트웨이가 에이전트를 실행하고 노드 도구를 호출할지 결정합니다.
  • 게이트웨이가 게이트웨이 WebSocket(node.* RPC)을 통해 노드를 호출합니다.
  • 노드가 결과를 반환하고, 게이트웨이가 Telegram으로 다시 응답합니다.

참고:

  • 노드는 게이트웨이 서비스를 실행하지 않습니다. 의도적으로 격리된 프로필을 실행하는 경우가 아니라면 호스트당 하나의 게이트웨이만 실행해야 합니다 (다중 게이트웨이 참고).
  • macOS 앱 “노드 모드”는 게이트웨이 WebSocket을 통한 노드 클라이언트일 뿐입니다.

SSH 터널 (CLI + 도구)

원격 게이트웨이 WS에 대한 로컬 터널을 만드세요:

ssh -N -L 18789:127.0.0.1:18789 user@host

터널이 활성화되면:

  • openclaw healthopenclaw status --deepws://127.0.0.1:18789를 통해 원격 게이트웨이에 연결됩니다.
  • openclaw gateway {status,health,send,agent,call}도 필요시 --url을 통해 포워딩된 URL을 대상으로 할 수 있습니다.

참고: 18789를 설정된 gateway.port (또는 --port/OPENCLAW_GATEWAY_PORT)로 교체하세요. 참고: --url을 전달하면 CLI는 설정이나 환경 인증 정보로 대체하지 않습니다. --token 또는 --password를 명시적으로 포함하세요. 명시적 인증 정보가 없으면 오류가 발생합니다.

CLI 원격 기본값

CLI 명령이 기본적으로 원격 대상을 사용하도록 영구 설정할 수 있습니다:

{
  gateway: {
    mode: "remote",
    remote: {
      url: "ws://127.0.0.1:18789",
      token: "your-token",
    },
  },
}

게이트웨이가 루프백 전용인 경우, URL을 ws://127.0.0.1:18789로 유지하고 먼저 SSH 터널을 여세요.

인증 정보 우선순위

게이트웨이 인증 정보 확인은 call/probe/status 경로 및 Discord 실행 승인 모니터링 전반에 걸쳐 하나의 공유 규칙을 따릅니다. 노드 호스트도 동일한 기본 규칙을 사용하지만, 로컬 모드에서 하나의 예외가 있습니다 (의도적으로 gateway.remote.*를 무시합니다):

  • 명시적 인증 정보 (--token, --password 또는 도구 gatewayToken)는 명시적 인증을 수용하는 호출 경로에서 항상 우선합니다.
  • URL 재정의 안전성:
    • CLI URL 재정의 (--url)는 암묵적 설정/환경 인증 정보를 재사용하지 않습니다.
    • 환경 URL 재정의 (OPENCLAW_GATEWAY_URL)는 환경 인증 정보만 사용할 수 있습니다 (OPENCLAW_GATEWAY_TOKEN / OPENCLAW_GATEWAY_PASSWORD).
  • 로컬 모드 기본값:
    • 토큰: OPENCLAW_GATEWAY_TOKEN -> gateway.auth.token -> gateway.remote.token (로컬 인증 토큰 입력이 미설정인 경우에만 원격 대체 적용)
    • 비밀번호: OPENCLAW_GATEWAY_PASSWORD -> gateway.auth.password -> gateway.remote.password (로컬 인증 비밀번호 입력이 미설정인 경우에만 원격 대체 적용)
  • 원격 모드 기본값:
    • 토큰: gateway.remote.token -> OPENCLAW_GATEWAY_TOKEN -> gateway.auth.token
    • 비밀번호: OPENCLAW_GATEWAY_PASSWORD -> gateway.remote.password -> gateway.auth.password
  • 노드 호스트 로컬 모드 예외: gateway.remote.token / gateway.remote.password가 무시됩니다.
  • 원격 probe/status 토큰 확인은 기본적으로 엄격합니다: 원격 모드를 대상으로 할 때 gateway.remote.token만 사용합니다 (로컬 토큰 대체 없음).
  • 레거시 CLAWDBOT_GATEWAY_* 환경 변수는 호환성 호출 경로에서만 사용됩니다. probe/status/인증 확인은 OPENCLAW_GATEWAY_*만 사용합니다.

SSH를 통한 Chat UI

WebChat은 더 이상 별도의 HTTP 포트를 사용하지 않습니다. SwiftUI 채팅 UI가 게이트웨이 WebSocket에 직접 연결됩니다.

  • SSH를 통해 18789를 포워딩한 후 (위 참고), 클라이언트를 ws://127.0.0.1:18789에 연결합니다.
  • macOS에서는 앱의 “원격 SSH 모드”를 선호하세요. 앱이 터널을 자동으로 관리합니다.

macOS 앱 “원격 SSH 모드”

macOS 메뉴 바 앱은 동일한 설정을 엔드투엔드로 구동할 수 있습니다 (원격 상태 확인, WebChat, Voice Wake 포워딩).

실행 가이드: macOS 원격 접근.

보안 규칙 (원격/VPN)

요약: 확실히 필요하지 않다면 게이트웨이를 루프백에만 바인딩하세요.

  • 루프백 + SSH/Tailscale Serve가 가장 안전한 기본값입니다 (공개 노출 없음).
  • 평문 ws://는 기본적으로 루프백 전용입니다. 신뢰할 수 있는 사설 네트워크의 경우, 클라이언트 프로세스에 OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1을 설정하세요 (긴급 조치).
  • 비루프백 바인딩 (lan/tailnet/custom 또는 루프백을 사용할 수 없을 때 auto)에는 인증 토큰/비밀번호가 필수입니다.
  • gateway.remote.token / .password는 클라이언트 인증 정보 소스입니다. 그 자체로 서버 인증을 설정하지는 않습니다.
  • 로컬 호출 경로에서 gateway.auth.*가 미설정인 경우에만 gateway.remote.*를 대체로 사용할 수 있습니다.
  • gateway.auth.token / gateway.auth.password가 SecretRef로 명시적 설정되었지만 확인되지 않으면, 확인이 폐쇄적으로 실패합니다 (원격 대체로 마스킹하지 않음).
  • wss:// 사용 시 gateway.remote.tlsFingerprint로 원격 TLS 인증서를 고정합니다.
  • Tailscale Servegateway.auth.allowTailscale: true일 때 ID 헤더를 통해 Control UI/WebSocket 트래픽을 인증할 수 있습니다. HTTP API 엔드포인트는 여전히 토큰/비밀번호 인증이 필요합니다. 이 토큰 없는 흐름은 게이트웨이 호스트를 신뢰한다고 가정합니다. 모든 곳에서 토큰/비밀번호를 원하면 false로 설정하세요.
  • 브라우저 제어를 운영자 접근과 동일하게 취급하세요: Tailnet 전용 + 의도적인 노드 페어링.

심화: 보안.