Remote access
Dostęp zdalny
To repo obsługuje „remote over SSH”, utrzymując pojedynczy Gateway (master) uruchomiony na dedykowanym hoście (desktop/serwer) i podłączając do niego klientów.
- Dla operatorów (Ty / aplikacja macOS): tunelowanie SSH jest uniwersalnym rozwiązaniem awaryjnym.
- Dla węzłów (iOS/Android i przyszłe urządzenia): łącz się z WebSocket Gateway (LAN/tailnet lub tunel SSH w razie potrzeby).
Główna idea
- WebSocket Gateway wiąże się z loopback na skonfigurowanym porcie (domyślnie 18789).
- Do użycia zdalnego przekierowujesz ten port loopback przez SSH (albo używasz tailnet/VPN i tunelujesz mniej).
Typowe konfiguracje VPN i tailnet
Pomyśl o hoście Gateway jako o miejscu, w którym działa agent. To on posiada sesje, profile uwierzytelniania, kanały i stan. Twój laptop, desktop i węzły łączą się z tym hostem.
Zawsze włączony Gateway w tailnet
Uruchom Gateway na trwałym hoście (VPS lub serwer domowy) i uzyskuj do niego dostęp przez Tailscale lub SSH.
- Najlepsze UX: pozostaw
gateway.bind: "loopback"i użyj Tailscale Serve dla Control UI. - Rozwiązanie awaryjne: pozostaw loopback plus tunel SSH z dowolnej maszyny, która potrzebuje dostępu.
- Przykłady: exe.dev (łatwa VM) lub Hetzner (produkcyjny VPS).
Idealne, gdy laptop często usypia, ale chcesz, aby agent był zawsze włączony.
Domowy desktop uruchamia Gateway
Laptop nie uruchamia agenta. Łączy się zdalnie:
- Użyj trybu Remote over SSH w aplikacji macOS (Settings → General → OpenClaw runs).
- Aplikacja otwiera tunel i nim zarządza, więc WebChat oraz kontrole zdrowia po prostu działają.
Runbook: zdalny dostęp macOS.
Laptop uruchamia Gateway
Zachowaj Gateway lokalnie, ale udostępnij go bezpiecznie:
- Tunel SSH do laptopa z innych maszyn albo
- Tailscale Serve dla Control UI i utrzymanie Gateway wyłącznie na loopback.
Przewodniki: Tailscale i omówienie Web.
Przepływ poleceń (co działa gdzie)
Jedna usługa gateway jest właścicielem stanu + kanałów. Węzły są urządzeniami peryferyjnymi.
Przykład przepływu (Telegram → węzeł):
- Wiadomość Telegram trafia do Gateway.
- Gateway uruchamia agenta i decyduje, czy wywołać narzędzie węzła.
- Gateway wywołuje węzeł przez WebSocket Gateway (
node.*RPC). - Węzeł zwraca wynik; Gateway odpowiada z powrotem do Telegram.
Uwagi:
- Węzły nie uruchamiają usługi gateway. Na host powinien działać tylko jeden gateway, chyba że celowo uruchamiasz izolowane profile (zobacz Wiele gatewayów).
- „Tryb węzła” aplikacji macOS to po prostu klient węzła przez WebSocket Gateway.
Tunel SSH (CLI + narzędzia)
Utwórz lokalny tunel do zdalnego Gateway WS:
ssh -N -L 18789:127.0.0.1:18789 user@host
Gdy tunel działa:
openclaw healthiopenclaw status --deepdocierają teraz do zdalnego gateway przezws://127.0.0.1:18789.openclaw gateway status,openclaw gateway health,openclaw gateway probeiopenclaw gateway callmogą także kierować na przekierowany URL przez--url, gdy jest to potrzebne.
Zdalne wartości domyślne CLI
Możesz utrwalić zdalny cel, aby polecenia CLI używały go domyślnie:
{
gateway: {
mode: "remote",
remote: {
url: "ws://127.0.0.1:18789",
token: "your-token",
},
},
}
Gdy gateway działa tylko na loopback, pozostaw URL jako ws://127.0.0.1:18789 i najpierw otwórz tunel SSH.
W transporcie tunelu SSH aplikacji macOS wykryte nazwy hostów gateway należą do
gateway.remote.sshTarget; gateway.remote.url pozostaje lokalnym URL-em tunelu.
Priorytet poświadczeń
Rozwiązywanie poświadczeń Gateway stosuje jeden wspólny kontrakt w ścieżkach call/probe/status oraz monitorowaniu zatwierdzeń wykonania Discord. Node-host używa tego samego kontraktu bazowego z jednym wyjątkiem trybu lokalnego (celowo ignoruje gateway.remote.*):
- Jawne poświadczenia (
--token,--passwordlub narzędziowegatewayToken) zawsze wygrywają na ścieżkach wywołań, które akceptują jawne uwierzytelnianie. - Bezpieczeństwo nadpisania URL:
- Nadpisania URL w CLI (
--url) nigdy nie używają ponownie niejawnych poświadczeń z konfiguracji/środowiska. - Nadpisania URL przez env (
OPENCLAW_GATEWAY_URL) mogą używać tylko poświadczeń env (OPENCLAW_GATEWAY_TOKEN/OPENCLAW_GATEWAY_PASSWORD).
- Nadpisania URL w CLI (
- Domyślne wartości trybu lokalnego:
- token:
OPENCLAW_GATEWAY_TOKEN->gateway.auth.token->gateway.remote.token(zdalne rozwiązanie awaryjne ma zastosowanie tylko wtedy, gdy lokalne wejście tokena auth jest nieustawione) - password:
OPENCLAW_GATEWAY_PASSWORD->gateway.auth.password->gateway.remote.password(zdalne rozwiązanie awaryjne ma zastosowanie tylko wtedy, gdy lokalne wejście hasła auth jest nieustawione)
- token:
- Domyślne wartości trybu zdalnego:
- token:
gateway.remote.token->OPENCLAW_GATEWAY_TOKEN->gateway.auth.token - password:
OPENCLAW_GATEWAY_PASSWORD->gateway.remote.password->gateway.auth.password
- token:
- Wyjątek trybu lokalnego Node-host:
gateway.remote.token/gateway.remote.passwordsą ignorowane. - Zdalne kontrole tokenów probe/status są domyślnie ścisłe: używają tylko
gateway.remote.token(bez lokalnego rozwiązania awaryjnego tokena), gdy celują w tryb zdalny. - Nadpisania env Gateway używają tylko
OPENCLAW_GATEWAY_*.
Chat UI przez SSH
WebChat nie używa już osobnego portu HTTP. Chat UI SwiftUI łączy się bezpośrednio z WebSocket Gateway.
- Przekieruj
18789przez SSH (zobacz wyżej), a następnie połącz klientów zws://127.0.0.1:18789. - Na macOS preferuj tryb „Remote over SSH” aplikacji, który automatycznie zarządza tunelem.
Aplikacja macOS Remote over SSH
Aplikacja paska menu macOS może obsłużyć tę samą konfigurację od początku do końca (zdalne kontrole statusu, WebChat i przekazywanie Voice Wake).
Runbook: zdalny dostęp macOS.
Reguły bezpieczeństwa (remote/VPN)
Krótka wersja: utrzymuj Gateway wyłącznie na loopback, chyba że masz pewność, że potrzebujesz wiązania.
- Loopback + SSH/Tailscale Serve to najbezpieczniejsza wartość domyślna (brak publicznej ekspozycji).
- Zwykły tekst
ws://jest domyślnie tylko dla loopback. Dla zaufanych sieci prywatnych ustawOPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1w procesie klienta jako awaryjne obejście. Nie ma odpowiednika wopenclaw.json; musi to być środowisko procesu klienta nawiązującego połączenie WebSocket. - Wiązania inne niż loopback (
lan/tailnet/customalboauto, gdy loopback jest niedostępny) muszą używać uwierzytelniania gateway: tokena, hasła lub reverse proxy świadomego tożsamości zgateway.auth.mode: "trusted-proxy". gateway.remote.token/.passwordsą źródłami poświadczeń klienta. Same nie konfigurują uwierzytelniania serwera.- Lokalne ścieżki wywołań mogą używać
gateway.remote.*jako rozwiązania awaryjnego tylko wtedy, gdygateway.auth.*jest nieustawione. - Jeśli
gateway.auth.token/gateway.auth.passwordjest jawnie skonfigurowane przez SecretRef i nierozwiązane, rozwiązywanie kończy się zamknięciem dostępu (bez maskowania przez zdalne rozwiązanie awaryjne). gateway.remote.tlsFingerprintprzypina zdalny certyfikat TLS przy użyciuwss://.- Tailscale Serve może uwierzytelniać ruch Control UI/WebSocket przez nagłówki
tożsamości, gdy
gateway.auth.allowTailscale: true; punkty końcowe HTTP API nie używają tego uwierzytelniania nagłówkiem Tailscale i zamiast tego stosują normalny tryb uwierzytelniania HTTP gateway. Ten przepływ bez tokena zakłada, że host gateway jest zaufany. Ustaw go nafalse, jeśli chcesz wszędzie używać uwierzytelniania współdzielonym sekretem. - Uwierzytelnianie Trusted-proxy domyślnie oczekuje konfiguracji proxy świadomego tożsamości poza loopback.
Reverse proxy na tym samym hoście przez loopback wymagają jawnego
gateway.auth.trustedProxy.allowLoopback = true. - Traktuj kontrolę z przeglądarki jak dostęp operatora: tylko tailnet + celowe parowanie węzłów.
Szczegóły: Bezpieczeństwo.
macOS: trwały tunel SSH przez LaunchAgent
Dla klientów macOS łączących się ze zdalnym gateway najprostsza trwała konfiguracja używa wpisu SSH LocalForward oraz LaunchAgent, aby utrzymać tunel przy życiu po restartach i awariach.
Krok 1: dodaj konfigurację SSH
Edytuj ~/.ssh/config:
Host remote-gateway
HostName <REMOTE_IP>
User <REMOTE_USER>
LocalForward 18789 127.0.0.1:18789
IdentityFile ~/.ssh/id_rsa
Zastąp <REMOTE_IP> i <REMOTE_USER> swoimi wartościami.
Krok 2: skopiuj klucz SSH (jednorazowo)
ssh-copy-id -i ~/.ssh/id_rsa <REMOTE_USER>@<REMOTE_IP>
Krok 3: skonfiguruj token gateway
Zapisz token w konfiguracji, aby przetrwał restarty:
openclaw config set gateway.remote.token "<your-token>"
Krok 4: utwórz LaunchAgent
Zapisz to jako ~/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>
Krok 5: załaduj LaunchAgent
launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist
Tunel uruchomi się automatycznie przy logowaniu, zrestartuje po awarii i utrzyma przekierowany port jako aktywny.
Rozwiązywanie problemów
Sprawdź, czy tunel działa:
ps aux | grep "ssh -N remote-gateway" | grep -v grep
lsof -i :18789
Zrestartuj tunel:
launchctl kickstart -k gui/$UID/ai.openclaw.ssh-tunnel
Zatrzymaj tunel:
launchctl bootout gui/$UID/ai.openclaw.ssh-tunnel
| Wpis konfiguracji | Co robi |
|---|---|
LocalForward 18789 127.0.0.1:18789 |
Przekierowuje lokalny port 18789 na zdalny port 18789 |
ssh -N |
SSH bez wykonywania zdalnych poleceń (tylko przekierowanie portów) |
KeepAlive |
Automatycznie restartuje tunel, jeśli ulegnie awarii |
RunAtLoad |
Uruchamia tunel, gdy LaunchAgent ładuje się przy logowaniu |