Remote access
リモートアクセス
このリポジトリは、専用ホスト(デスクトップ/サーバー)で単一の Gateway(マスター)を実行し、クライアントをそこへ接続することで、「SSH 経由のリモート」をサポートします。
- オペレーター(あなた / macOS アプリ)向け: SSH トンネリングが汎用フォールバックです。
- ノード(iOS/Android および将来のデバイス)向け: 必要に応じて(LAN/tailnet または SSH トンネルで)Gateway WebSocket に接続します。
中心となる考え方
- Gateway WebSocket は、設定済みポート(デフォルトは 18789)の loopback にバインドします。
- リモート利用では、その loopback ポートを SSH 経由で転送します(または tailnet/VPN を使ってトンネルを減らします)。
一般的な VPN と tailnet 構成
Gateway ホストはエージェントが存在する場所だと考えてください。セッション、認証プロファイル、チャネル、状態を所有します。あなたのラップトップ、デスクトップ、ノードはそのホストに接続します。
tailnet 内の常時稼働 Gateway
永続ホスト(VPS またはホームサーバー)で Gateway を実行し、Tailscale または SSH で到達します。
- 最適な UX:
gateway.bind: "loopback"を維持し、Control UI には Tailscale Serve を使用します。 - フォールバック: loopback を維持し、アクセスが必要な任意のマシンから SSH トンネルを使います。
- 例: exe.dev(簡単な VM)または Hetzner(本番 VPS)。
ラップトップが頻繁にスリープするが、エージェントは常時稼働させたい場合に理想的です。
ホームデスクトップが Gateway を実行する
ラップトップはエージェントを実行しません。リモートで接続します。
- macOS アプリの Remote over SSH モードを使用します(Settings → General → OpenClaw runs)。
- アプリがトンネルを開いて管理するため、WebChat とヘルスチェックがそのまま機能します。
ランブック: macOS リモートアクセス。
ラップトップが Gateway を実行する
Gateway をローカルに保ちつつ、安全に公開します。
- 他のマシンからラップトップへ SSH トンネルを張る、または
- Control UI を Tailscale Serve し、Gateway は loopback 専用のままにします。
コマンドフロー(どこで何が実行されるか)
1 つの gateway サービスが状態とチャネルを所有します。ノードは周辺機器です。
フロー例(Telegram → ノード):
- Telegram メッセージが Gateway に到着します。
- Gateway がエージェントを実行し、ノードツールを呼び出すかどうかを判断します。
- Gateway が Gateway WebSocket 経由でノードを呼び出します(
node.*RPC)。 - ノードが結果を返し、Gateway が Telegram へ返信します。
注記:
- ノードは gateway サービスを実行しません。 意図的に分離プロファイルを実行する場合を除き、ホストごとに 1 つの gateway のみを実行してください(複数の gateway を参照)。
- macOS アプリの「ノードモード」は、Gateway WebSocket 経由の単なるノードクライアントです。
SSH トンネル(CLI + ツール)
リモート Gateway WS へのローカルトンネルを作成します。
ssh -N -L 18789:127.0.0.1:18789 user@host
トンネルが起動している状態では:
openclaw healthとopenclaw status --deepは、ws://127.0.0.1:18789経由でリモート gateway に到達します。openclaw gateway status、openclaw gateway health、openclaw gateway probe、openclaw gateway callも、必要に応じて--urlで転送先 URL を対象にできます。
CLI リモートデフォルト
CLI コマンドがデフォルトで使用するリモートターゲットを永続化できます。
{
gateway: {
mode: "remote",
remote: {
url: "ws://127.0.0.1:18789",
token: "your-token",
},
},
}
gateway が loopback 専用の場合は、URL を ws://127.0.0.1:18789 のままにし、先に SSH トンネルを開いてください。
macOS アプリの SSH トンネル transport では、検出された gateway ホスト名は
gateway.remote.sshTarget に属します。gateway.remote.url はローカルトンネル URL のままです。
認証情報の優先順位
Gateway 認証情報の解決は、call/probe/status パスと Discord exec-approval 監視にわたって、1 つの共有コントラクトに従います。Node-host は、1 つのローカルモード例外(意図的に gateway.remote.* を無視します)を除き、同じ基本コントラクトを使用します。
- 明示的な認証情報(
--token、--password、またはツールのgatewayToken)は、明示的認証を受け付ける call パスでは常に優先されます。 - URL オーバーライドの安全性:
- CLI URL オーバーライド(
--url)は、暗黙の config/env 認証情報を再利用しません。 - Env URL オーバーライド(
OPENCLAW_GATEWAY_URL)は、env 認証情報のみを使用できます(OPENCLAW_GATEWAY_TOKEN/OPENCLAW_GATEWAY_PASSWORD)。
- CLI URL オーバーライド(
- ローカルモードのデフォルト:
- token:
OPENCLAW_GATEWAY_TOKEN->gateway.auth.token->gateway.remote.token(リモートフォールバックは、ローカル認証トークン入力が未設定の場合にのみ適用されます) - password:
OPENCLAW_GATEWAY_PASSWORD->gateway.auth.password->gateway.remote.password(リモートフォールバックは、ローカル認証パスワード入力が未設定の場合にのみ適用されます)
- token:
- リモートモードのデフォルト:
- token:
gateway.remote.token->OPENCLAW_GATEWAY_TOKEN->gateway.auth.token - password:
OPENCLAW_GATEWAY_PASSWORD->gateway.remote.password->gateway.auth.password
- token:
- Node-host ローカルモード例外:
gateway.remote.token/gateway.remote.passwordは無視されます。 - リモート probe/status のトークンチェックはデフォルトで厳格です。リモートモードを対象にする場合、
gateway.remote.tokenのみを使用します(ローカルトークンへのフォールバックはありません)。 - Gateway env オーバーライドは
OPENCLAW_GATEWAY_*のみを使用します。
SSH 経由の Chat UI
WebChat は個別の HTTP ポートを使用しなくなりました。SwiftUI チャット UI は Gateway WebSocket に直接接続します。
- SSH 経由で
18789を転送し(上記参照)、クライアントをws://127.0.0.1:18789に接続します。 - macOS では、トンネルを自動管理するアプリの「Remote over SSH」モードを推奨します。
macOS アプリの Remote over SSH
macOS メニューバーアプリは、同じ構成をエンドツーエンドで駆動できます(リモートステータスチェック、WebChat、Voice Wake 転送)。
ランブック: macOS リモートアクセス。
セキュリティルール(remote/VPN)
短く言うと、バインドが必要だと確信できない限り、Gateway は loopback 専用に保ってください。
- Loopback + SSH/Tailscale Serve が最も安全なデフォルトです(公開露出なし)。
- 平文の
ws://はデフォルトで loopback 専用です。信頼済みプライベートネットワークでは、 緊急回避としてクライアントプロセスでOPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1を設定します。 同等のopenclaw.json設定はありません。これは WebSocket 接続を行うクライアントの プロセス環境でなければなりません。 - 非 loopback バインド(
lan/tailnet/custom、または loopback が利用できない場合のauto)では、gateway 認証を使用する必要があります: token、password、またはgateway.auth.mode: "trusted-proxy"を持つ identity-aware リバースプロキシ。 gateway.remote.token/.passwordはクライアント認証情報ソースです。それ自体ではサーバー認証を構成しません。- ローカル call パスは、
gateway.auth.*が未設定の場合にのみgateway.remote.*をフォールバックとして使用できます。 gateway.auth.token/gateway.auth.passwordが SecretRef 経由で明示的に設定され、未解決の場合、解決は fail closed します(リモートフォールバックによる隠蔽はありません)。gateway.remote.tlsFingerprintは、wss://使用時にリモート TLS 証明書をピン留めします。- Tailscale Serve は、
gateway.auth.allowTailscale: trueの場合、identity ヘッダー経由で Control UI/WebSocket トラフィックを認証できます。HTTP API エンドポイントは その Tailscale ヘッダー認証を使用せず、gateway の通常の HTTP 認証モードに従います。このトークンなしフローは、gateway ホストが信頼済みであることを前提とします。 すべての場所で共有シークレット認証を使いたい場合は、falseに設定してください。 - Trusted-proxy 認証は、デフォルトで非 loopback の identity-aware proxy 構成を想定します。
同一ホスト上の loopback リバースプロキシには、明示的に
gateway.auth.trustedProxy.allowLoopback = trueが必要です。 - ブラウザー制御はオペレーターアクセスと同様に扱います: tailnet 専用 + 意図的なノードペアリング。
詳細: セキュリティ。
macOS: LaunchAgent による永続 SSH トンネル
リモート gateway に接続する macOS クライアントでは、SSH LocalForward config エントリと LaunchAgent を使って、再起動やクラッシュをまたいでトンネルを維持するのが最も簡単な永続構成です。
ステップ 1: SSH config を追加する
~/.ssh/config を編集します。
Host remote-gateway
HostName <REMOTE_IP>
User <REMOTE_USER>
LocalForward 18789 127.0.0.1:18789
IdentityFile ~/.ssh/id_rsa
<REMOTE_IP> と <REMOTE_USER> を自分の値に置き換えます。
ステップ 2: SSH キーをコピーする(1 回のみ)
ssh-copy-id -i ~/.ssh/id_rsa <REMOTE_USER>@<REMOTE_IP>
ステップ 3: gateway トークンを構成する
再起動後も保持されるように、トークンを config に保存します。
openclaw config set gateway.remote.token "<your-token>"
ステップ 4: LaunchAgent を作成する
これを ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist として保存します。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>ai.openclaw.ssh-tunnel</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/ssh</string>
<string>-N</string>
<string>remote-gateway</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
ステップ 5: LaunchAgent を読み込む
launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist
トンネルはログイン時に自動起動し、クラッシュ時に再起動し、転送ポートを稼働状態に保ちます。
トラブルシューティング
トンネルが実行中か確認します。
ps aux | grep "ssh -N remote-gateway" | grep -v grep
lsof -i :18789
トンネルを再起動します。
launchctl kickstart -k gui/$UID/ai.openclaw.ssh-tunnel
トンネルを停止します。
launchctl bootout gui/$UID/ai.openclaw.ssh-tunnel
| Config エントリ | 役割 |
|---|---|
LocalForward 18789 127.0.0.1:18789 |
ローカルポート 18789 をリモートポート 18789 に転送します |
ssh -N |
リモートコマンドを実行しない SSH(ポート転送のみ) |
KeepAlive |
クラッシュした場合にトンネルを自動的に再起動します |
RunAtLoad |
ログイン時に LaunchAgent が読み込まれたときトンネルを開始します |