공인 HTTP 없이 다중 리전 vpshalo에서 OpenClaw를 묶습니다. frp STCP·gateway·doctor는
127.0.0.1, 토큰·시크릿 통과 후 헬스는 리전당 한 알림. SSH 글과 동일한 저노출입니다.
대안: MagicDNS·SSH -R·STCP. 맥락: GeoDNS, Tunnel, JumpHost. 숨김=visitor+토큰 / 인증=auth.token+secretKey / 분리=PoP별 이름 / 페이징=5분 창에서 gw·doctor 동시 실패만.
CTA(공개): 첫 페이지·요금제·도움말·구매·블로그.
역할·포트·gateway/doctor 연쇄
frps:7000·토큰.frpc(Mac):openclaw-{region}-gw→127.0.0.1:18080(gateway), -doctor→127.0.0.1:18081, 시크릿 분리.visitor:127.0.0.1:28080·28081. curl http://127.0.0.1:28080/healthz로 전체 사슬 검증.
최소 재현 절차
- 1
OPENCLAW_HOME분리,--gateway-bind 127.0.0.1:18080 --doctor-bind 127.0.0.1:18081, 로컬/healthz·/doctor. - 2 배스천
frps7000·auth.token, 방화벽은 운영·빌더만. - 3 빌더
frpcSTCP gw·doctor, 시크릿 분리, 공인 포트 없음. - 4 visitor
127.0.0.1:28080·28081, 시크릿 일치 확인. - 5 워커가 두 레인 조인, 5분 창 동시 실패만 페이징.
# frpc.toml — 빌더 측, loopback에 STCP 두 개
serverAddr = "bastion-sin.vpshalo.example"
serverPort = 7000
auth.method = "token"
auth.token = "<long-random-frps-token>"
[[proxies]]
name = "openclaw-sin-gw"
type = "stcp"
secretKey = "<sk-sin-gw>"
localIP = "127.0.0.1"
localPort = 18080
[[proxies]]
name = "openclaw-sin-doctor"
type = "stcp"
secretKey = "<sk-sin-doctor>"
localIP = "127.0.0.1"
localPort = 18081
# frpc.toml — visitor 측, 두 레인 모두 127.0.0.1
[[visitors]]
name = "v-openclaw-sin-gw"
type = "stcp"
serverName = "openclaw-sin-gw"
secretKey = "<sk-sin-gw>"
bindAddr = "127.0.0.1"
bindPort = 28080
[[visitors]]
name = "v-openclaw-sin-doctor"
type = "stcp"
serverName = "openclaw-sin-doctor"
secretKey = "<sk-sin-doctor>"
bindAddr = "127.0.0.1"
bindPort = 28081
브라우저가 필요하면 visitor 앞 리버스 프록시에서 TLS 종료. visitor를
0.0.0.0으로 올리지 마세요.문제 해결
연결 실패 → 7000·ACL·frps 로그(토큰 vs 시크릿). gw OK·doctor만 지연 → OpenClaw 재시작. 지연 큼 → 배스천 근접 PoP, RTT. 교체 직후 → visitor·프록시 시크릿 동시 반영 후 curl 127.0.0.1:28080/healthz. 동시 다운 → 터널·frpc 감독.
면책: frp·OpenClaw 플래그는 버전별 상이. 스크립트화 시 loopback·STCP·리전당 병합 알림을 유지하고 PoP는 RTT 기준으로 고릅니다.