SSH와 Tailnet을 활용한 Gateway 원격 접속 가이드
집에 있는 고성능 데스크톱에서 실행 중인 AI 에이전트를 외부에서 노트북만으로 제어하고 싶을 때가 있죠? 하지만 보안 설정이나 복잡한 네트워크 구성 때문에 포기하셨던 분들이 많을 거예요.
이 가이드는 SSH 터널링과 Tailscale 같은 도구를 활용해 어디서나 안전하고 간편하게 Gateway에 접속하는 방법을 설명해 드려요. 복잡한 설정 없이도 마치 로컬에서 사용하는 것처럼 매끄러운 환경을 만들 수 있습니다.
원격 접속 (SSH, 터널링, 그리고 tailnet)
섹션 제목: “원격 접속 (SSH, 터널링, 그리고 tailnet)”이 레포지토리는 전용 호스트(데스크톱/서버)에서 단일 Gateway(마스터)를 실행하고 클라이언트를 여기에 연결하는 “SSH를 통한 원격 접속”을 지원해요.
- 운영자 (사용자 / macOS 앱): SSH 터널링은 가장 범용적인 해결책이에요.
- 노드 (iOS/Android 및 향후 기기): 필요에 따라 Gateway WebSocket(LAN/tailnet 또는 SSH 터널)에 연결하세요.
핵심 개념
섹션 제목: “핵심 개념”- Gateway WebSocket은 설정된 포트(기본값 18789)의 loopback에 바인딩돼요.
- 원격으로 사용하려면 해당 loopback 포트를 SSH로 포워딩하거나, tailnet/VPN을 사용해서 터널링을 최소화하면 돼요.
일반적인 VPN/tailnet 설정 (에이전트 위치)
섹션 제목: “일반적인 VPN/tailnet 설정 (에이전트 위치)”Gateway 호스트를 “에이전트가 사는 곳”이라고 생각하세요. 이 호스트가 세션, 인증 프로필, 채널, 상태를 모두 소유해요. 여러분의 노트북이나 데스크톱(그리고 노드들)이 이 호스트에 접속하는 구조예요.
1) Tailnet에 항상 켜져 있는 Gateway (VPS 또는 홈 서버)
섹션 제목: “1) Tailnet에 항상 켜져 있는 Gateway (VPS 또는 홈 서버)”항상 켜져 있는 호스트에서 Gateway를 실행하고 Tailscale이나 SSH를 통해 접속하세요.
- 가장 좋은 UX:
gateway.bind: "loopback"설정을 유지하고, Control UI용으로 Tailscale Serve를 사용하세요. - 대안: loopback 설정을 유지하면서 접속이 필요한 기기에서 SSH 터널을 사용하세요.
- 예시: exe.dev (간편한 VM) 또는 Hetzner (프로덕션 VPS).
노트북을 자주 끄지만 에이전트는 항상 켜두고 싶을 때 이상적인 방법이에요.
2) 홈 데스크톱에서 Gateway 실행, 노트북은 원격 제어
섹션 제목: “2) 홈 데스크톱에서 Gateway 실행, 노트북은 원격 제어”노트북에서는 에이전트를 실행하지 않아요. 대신 원격으로 연결하죠.
- macOS 앱의 Remote over SSH 모드를 사용하세요 (Settings → General → “OpenClaw runs”).
- 앱이 터널을 직접 열고 관리하기 때문에 WebChat과 상태 확인(health checks)이 문제없이 작동해요.
실행 가이드: macOS remote access.
3) 노트북에서 Gateway 실행, 다른 기기에서 원격 접속
섹션 제목: “3) 노트북에서 Gateway 실행, 다른 기기에서 원격 접속”Gateway를 로컬에 두되 안전하게 노출하는 방법이에요.
- 다른 기기에서 노트북으로 SSH 터널을 연결하거나,
- Control UI를 Tailscale Serve로 제공하고 Gateway는 loopback 전용으로 유지하세요.
가이드: Tailscale 및 Web overview.
명령 흐름 (어디에서 무엇이 실행되는가)
섹션 제목: “명령 흐름 (어디에서 무엇이 실행되는가)”하나의 Gateway 서비스가 상태와 채널을 소유해요. 노드는 주변 장치 역할을 하죠.
흐름 예시 (Telegram → 노드):
- Telegram 메시지가 Gateway에 도착해요.
- Gateway가 에이전트를 실행하고 노드 도구를 호출할지 결정해요.
- Gateway가 Gateway WebSocket(
node.*RPC)을 통해 노드를 호출해요. - 노드가 결과를 반환하면 Gateway가 다시 Telegram으로 응답을 보내요.
참고:
- 노드는 Gateway 서비스를 실행하지 않아요. 의도적으로 격리된 프로필을 실행하는 경우가 아니라면 호스트당 하나의 Gateway만 실행해야 해요 (Multiple gateways 참고).
- macOS 앱의 “노드 모드”는 Gateway WebSocket을 통한 노드 클라이언트일 뿐이에요.
SSH 터널 (CLI 및 도구)
섹션 제목: “SSH 터널 (CLI 및 도구)”원격 Gateway WebSocket으로 연결되는 로컬 터널을 생성하세요.
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,health,send,agent,call}명령어에--url을 사용해 포워딩된 URL을 직접 지정할 수 있어요.
참고: 18789를 여러분이 설정한 gateway.port (또는 --port/OPENCLAW_GATEWAY_PORT)로 바꾸세요.
참고: --url을 전달할 때 CLI는 설정 파일이나 환경 변수의 자격 증명을 자동으로 사용하지 않아요.
--token이나 --password를 명시적으로 포함해야 해요. 자격 증명이 누락되면 에러가 발생해요.
CLI 원격 기본값
섹션 제목: “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 터널을 먼저 여세요.
자격 증명 우선순위
섹션 제목: “자격 증명 우선순위”Gateway 자격 증명 확인은 call/probe/status 경로와 Discord 실행 승인 모니터링 전체에서 공통된 규칙을 따라요. Node-host도 동일한 기본 규칙을 사용하지만, 로컬 모드에서 한 가지 예외가 있어요 (의도적으로 gateway.remote.*를 무시해요).
- 명시적 자격 증명(
--token,--password, 또는 도구의gatewayToken)은 명시적 인증을 허용하는 경로에서 항상 우선해요. - URL 오버라이드 안전 규칙:
- CLI URL 오버라이드(
--url)는 설정이나 환경 변수의 암시적 자격 증명을 재사용하지 않아요. - 환경 변수 URL 오버라이드(
OPENCLAW_GATEWAY_URL)는 환경 변수 자격 증명(OPENCLAW_GATEWAY_TOKEN/OPENCLAW_GATEWAY_PASSWORD)만 사용할 수 있어요.
- CLI URL 오버라이드(
- 로컬 모드 기본값:
- token:
OPENCLAW_GATEWAY_TOKEN->gateway.auth.token->gateway.remote.token(로컬 인증 토큰 입력이 없을 때만 원격 fallback 적용) - password:
OPENCLAW_GATEWAY_PASSWORD->gateway.auth.password->gateway.remote.password(로컬 인증 패스워드 입력이 없을 때만 원격 fallback 적용)
- 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만 사용해요 (로컬 토큰 fallback 없음). - Gateway 환경 변수 오버라이드는
OPENCLAW_GATEWAY_*만 사용해요.
SSH를 통한 Chat UI
섹션 제목: “SSH를 통한 Chat UI”WebChat은 더 이상 별도의 HTTP 포트를 사용하지 않아요. SwiftUI 기반의 Chat UI는 Gateway WebSocket에 직접 연결돼요.
- 위에서 설명한 대로 SSH를 통해
18789포트를 포워딩한 후, 클라이언트를ws://127.0.0.1:18789에 연결하세요. - macOS에서는 터널을 자동으로 관리해 주는 앱의 “Remote over SSH” 모드를 사용하는 것이 좋아요.
macOS 앱 “Remote over SSH”
섹션 제목: “macOS 앱 “Remote over SSH””macOS 메뉴바 앱은 원격 상태 확인, WebChat, Voice Wake 포워딩 등 모든 설정을 처음부터 끝까지 관리할 수 있어요.
실행 가이드: macOS remote access.
보안 규칙 (원격/VPN)
섹션 제목: “보안 규칙 (원격/VPN)”요약하자면, Gateway를 loopback 전용으로 유지하세요. 바인딩이 꼭 필요한 경우가 아니라면요.
- Loopback + SSH/Tailscale Serve 조합이 가장 안전한 기본값이에요 (공개 노출 없음).
- 일반 텍스트
ws://는 기본적으로 loopback 전용이에요. 신뢰할 수 있는 사설 네트워크의 경우, 클라이언트 프로세스에서OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1을 설정해 강제로 연결할 수 있어요. - Loopback이 아닌 바인드(
lan/tailnet/custom, 또는 loopback을 사용할 수 없을 때의auto)는 반드시 인증 토큰이나 패스워드를 사용해야 해요. gateway.remote.token/.password는 클라이언트용 자격 증명이에요. 이것만으로 서버 인증이 설정되지는 않아요.- 로컬 호출 경로는
gateway.auth.*가 설정되지 않은 경우에만gateway.remote.*를 fallback으로 사용할 수 있어요. gateway.auth.token/gateway.auth.password가 SecretRef를 통해 명시적으로 설정되었지만 해결되지 않은 경우, 보안을 위해 원격 fallback 없이 실패 처리돼요.wss://를 사용할 때gateway.remote.tlsFingerprint로 원격 TLS 인증서를 고정(pinning)할 수 있어요.- Tailscale Serve는
gateway.auth.allowTailscale: true설정 시 ID 헤더를 통해 Control UI/WebSocket 트래픽을 인증할 수 있어요. 단, HTTP API 엔드포인트는 여전히 토큰/패스워드 인증이 필요해요. 이 토큰 없는 흐름은 Gateway 호스트를 신뢰할 수 있다고 가정해요. 모든 곳에 토큰/패스워드를 적용하려면false로 설정하세요. - 브라우저 제어는 운영자 접속과 동일하게 취급하세요. tailnet 전용 접속과 의도적인 노드 페어링을 권장해요.
상세 내용: Security.
macOS: LaunchAgent를 통한 지속적인 SSH 터널
섹션 제목: “macOS: LaunchAgent를 통한 지속적인 SSH 터널”원격 Gateway에 연결하는 macOS 클라이언트의 경우, SSH LocalForward 설정과 LaunchAgent를 조합해 재부팅이나 충돌 시에도 터널이 유지되도록 하는 것이 가장 편해요.
1단계: SSH 설정 추가
섹션 제목: “1단계: SSH 설정 추가”~/.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회)
섹션 제목: “2단계: SSH 키 복사 (최초 1회)”ssh-copy-id -i ~/.ssh/id_rsa <REMOTE_USER>@<REMOTE_IP>3단계: Gateway 토큰 설정
섹션 제목: “3단계: Gateway 토큰 설정”재시작 후에도 유지되도록 토큰을 설정에 저장하세요:
openclaw config set gateway.remote.token "<your-token>"4단계: LaunchAgent 생성
섹션 제목: “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 로드
섹션 제목: “5단계: LaunchAgent 로드”launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist이제 터널이 로그인 시 자동으로 시작되고, 문제가 생기면 재시작되며, 포워딩된 포트를 계속 유지해 줘요.
참고: 이전 설정에서 남은 com.openclaw.ssh-tunnel LaunchAgent가 있다면 언로드하고 삭제하세요.
문제 해결
섹션 제목: “문제 해결”터널이 실행 중인지 확인하려면:
ps aux | grep "ssh -N remote-gateway" | grep -v greplsof -i :18789터널 재시작:
launchctl kickstart -k gui/$UID/ai.openclaw.ssh-tunnel터널 중지:
launchctl bootout gui/$UID/ai.openclaw.ssh-tunnel| 설정 항목 | 역할 |
|---|---|
LocalForward 18789 127.0.0.1:18789 | 로컬 18789 포트를 원격 18789 포트로 전달 |
ssh -N | 원격 명령 실행 없이 SSH 연결 (포트 포워딩 전용) |
KeepAlive | 터널이 중단되면 자동으로 재시작 |
RunAtLoad | 로그인 시 LaunchAgent가 로드될 때 터널 시작 |
다음 단계
섹션 제목: “다음 단계”궁금한 점이 있나요? AI Setup Assistant에게 물어보세요!
OpenClaw Expert
아직 막혀 있나요?
이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.