컨테이너 안에서는 정상인데 Nginx/Caddy 뒤에 두면 502, WebSocket 핸드셰이크 실패, 끝없는 리다이렉트가 난다면? 이 글은 엣지 리버스 프록시 + TLS 종료 + WebSocket 업그레이드 층에 초점을 맞춘다. Docker 네트워크 분기와 짝을 이룬다: 그 글은 패킷 도달성, 여기서는 브라우저에서 Gateway까지의 HTTP/1.1 업그레이드 경로와 경로 정합성을 다룬다. 여섯 가지 흔한 함정, 토폴로지·증상 대조표, 복사 가능한 스니펫, 6단계 프로덕션 Runbook, 온콜 지표 세 가지를 제공한다. 읽은 뒤에는 Upgrade 헤더를 고칠지 업스트림 127.0.0.1:18789로 돌아갈지 판단할 수 있다.
proxy_pass만 있고 HTTP/1.1과 Upgrade가 없음: WebSocket 사용 시 엣지에서 400/502가 나고 로그는 Gateway 장애처럼 보인다./openclaw를 제거해도 앱이 루트 기준 절대 URL을 보내 정적 자산과 WS 경로가 갈라진다.proxy_read_timeout이 너무 짧음: 긴 추론이나 채널 트래픽 버스트 시 엣지가 조용히 끊어 재연결 폭풍이 업스트림을 때린다.아래 토폴로지 표로 동일 호스트/별도 호스트/서브도메인/서브패스 트레이드오프를 정리한 뒤 헤더 체크리스트와 증상 매트릭스로 넘어간다.
동일 호스트 리버스 프록시(Nginx/Caddy와 Gateway 공존)는 가장 짧은 경로로, curl -v http://127.0.0.1:18789로 업스트림을 검증할 수 있다. 별도 프록시 호스트는 홉이 늘어 보안 그룹, 내부 DNS, TLS SNI를 다시 확인한다. 서브도메인은 경로 제거와 Cookie Path 충돌을 피하기 쉽다. 서브패스는 단일 브랜드 진입 도메인에 맞지만 OpenClaw 베이스 URL과 프록시 양쪽에서 접두사는 한 번만 제거하고, 개발자 도구로 WS URL이 기대하는 wss:// 경로를 가리키는지 확인한다.
변경 요청에는 스크린샷 두 장을 필수로 첨부한다: 최종 주소창 URL과 Network 탭의 WebSocket 핸드셰이크 Request URL. 없으면 리뷰가 모델 타임아웃이나 채널 OAuth로 잘못 분류되어 릴리스 시간을 낭비한다. 기업 HTTPS 프록시가 있다면 사무실 브라우저(PAC 주입)와 데이터센터 프록시(대개 직결) 경로를 분리해 생각한다. 증상 불일치는 흔한 일이다.
2026년에도 엣지 HTTP/2와 업스트림 HTTP/1.1 WebSocket 조합은 흔하다. 어떤 홉에서 업그레이드가 허용되는지 확인한다. 패킷 캡처 없이 강제 H2와 사용자 정의 WS 재작성을 동시에 켜지 않는다.
| 토폴로지 | 적합 | 운영 이점 | 전형적 함정 |
|---|---|---|---|
| 동일 호스트 + 루프백 업스트림 | 단일 VPS / 상시 원격 Mac | 로컬 curl 분기, TLS와 프로세스가 같은 로그 | 0.0.0.0 바인딩으로 노출 확대, 방화벽 필요 |
| 전용 프록시 호스트 | 다중 백엔드, 블루/그린, WAF 전방 | 엣지와 컴퓨트 풀 분리, 인증서 갱신 집중 | 내부 라우팅, SNI, 헬스 체크 대상 드리프트 |
| 서브도메인 | WS를 메인 사이트와 분리 | 경로 의미가 분명, CDN 규칙 작성 용이 | 다중 인증서, HSTS는 별도 검토 |
| 서브패스 | 단일 브랜드 진입 도메인 | 사용자 기억 부담 낮음 | 접두사 제거, 리다이렉트 루프, 자산 루트 불일치 |
구현과 관계없이 엣지는 HTTP/1.1로 업그레이드하고, Connection: upgrade와 Upgrade: websocket을 통과 또는 재구성하며, 모델 최저 백분위보다 긴 읽기 타임아웃을 둔다. 표는 코드 리뷰 체크리스트다.
놓치기 쉬운 것은 프록시 버퍼링이다. 일반 API에서는 proxy_buffering이 처리량에 도움이 될 수 있지만 스트리밍이나 장수명 연결에서는 지연과 끊김 인상을 줄 수 있다. 스트림형 채널이나 SSE 유사 동작이 있으면 스테이징에서 실부하로 검증한 뒤 기본 버퍼를 켠다.
| 점검 항목 | Nginx 요점 | Caddy 요점 |
|---|---|---|
| 프로토콜 버전 | proxy_http_version 1.1; | reverse_proxy 기본 HTTP/1.1, 명시 transport 주의 |
| Upgrade 체인 | Upgrade $http_upgrade; Connection "upgrade"; | 대부분 자동, 사용자 정의는 header_up |
| Host와 클라이언트 IP | proxy_set_header Host $host;, X-Forwarded-* | header_up Host {host}, 프록시 홉 신뢰 |
| 장수명 연결 | proxy_read_timeout / send_timeout | transport http { read_timeout ... }(버전별 문법은 문서 참고) |
| 큰 본문 | client_max_body_size | 본문 제한 지시문(Caddy 문서 참고) |
# 스니펫: 로컬 Gateway로 리버스 프록시(포트는 배포에 맞게, 예 18789)
location / {
proxy_pass http://127.0.0.1:18789;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
# 스니펫: 자동 TLS + WebSocket 업스트림
openclaw.example.com {
reverse_proxy 127.0.0.1:18789 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
팁: 변경 후에는 먼저 업스트림에서 curl -v -H "Connection: Upgrade" -H "Upgrade: websocket" http://127.0.0.1:18789/로 핸드셰이크 의미를 검증하고, 그다음 공개 wss://를 시험한다. 그렇지 않으면 TLS와 프록시 사이에서 책임이 오간다.
증상을 엣지·업스트림·앱 설정에 매핑한 뒤 컨테이너를 재구성한다. 표가 컨테이너 네트워크를 가리키면 Docker 네트워크 분기로, 채널은 연결됐는데 Slack/Telegram이 침묵이면 채널 연결 문제 해결을 본다.
프로덕션에서만 재현되고 스테이징은 정상이면 인증서 체인 CA, CDN/WAF 규칙 버전, 프록시 map/if가 특정 User-Agent로 분기하는지 차이를 비교한다. 많은 502는 엣지 규칙 오탐이며 OpenClaw 버전과 무관하다.
| 현상 | 우선 의심 | 검증 |
|---|---|---|
| 502 Bad Gateway | 업스트림 미리슨, 방화벽, 잘못된 소켓 패밀리 | 프록시에서 업스트림 curl, error.log의 upstream timed out / refused |
| 413 Request Entity Too Large | 엣지 client_max_body_size 과소 | 값 상향 후 reload, CDN/WAF 한도 동기화 |
| WS가 101이 아님 | Upgrade 누락, 경로 재작성, http→https 리다이렉트가 핸드셰이크 파손 | 브라우저 Network에서 핸드셰이크 상태, location 순서와 return 301 |
| 리다이렉트 루프 | X-Forwarded-Proto 없이 HTTPS 강제 | 테스트 시 엣지 HSTS 완화, forwarded 헤더 보강 |
| 인증서 경고 / 일부 클라이언트만 실패 | 체인 불완전, 잘못된 SNI, IP 인증서 혼용 | openssl s_client -servername로 체인 확인, NTP |
https:// 베이스, 서브패스 여부, WS가 HTTP와 동일 host인지 문서화.18789).127.0.0.1:18789 또는 내부 VIP까지. 공용 지연과 분리해 느림이 엣지인지 Gateway인지 판단하기 쉽다.중앙 로그가 있다면 프록시 access 5xx 비율과 Gateway 애플리케이션 오류율을 이중 축으로 맞춘다. 한쪽만 치솟을 때 책임 경계가 분명하고 사후 분석이 감이 아니라 데이터로 말한다.
노트북 리버스 프록시 실험은 스니펫 검증에는 빠르지만, 절전, VPN 전환, 불안정한 가정용 업링크는 TLS와 갱신을 수작업으로 만든다. 502 SLO를 계약으로 내리기 어렵다. 리버스 프록시 + 상시 Gateway를 24/7 전용 호스트(예: 임대 Apple Silicon 클라우드 Mac 또는 관리형 VPS)에 두면 속도 제한, 인증서, 로그 보존이 표준 변경이 된다. 입구가 안정돼야 OpenClaw와 CI, 서명 파이프라인 연동이 감사와 인수인계에 견딘다.
자체 리버스 프록시 스택은 OpenSSL, Nginx, OS CVE 추적도 필요하다. OpenClaw를 CI, 서명, 다채널 봇에 장기적으로 묶는 팀에게 예측 가능한 전용 연산과 명확한 리전·임대 기간이 가정용 출구 실험보다 총비용에서 유리한 경우가 많다. MACCOME 클라우드 Mac은 다중 리전과 명확한 렌탈 구간을 제공해 TLS 종단 뒤의 깨끗한 상시 머신으로 적합하다. 먼저 3플랫폼 설치·선택 가이드로 디렉터리와 권한 경계를 고정하고, Mac mini 대여 가격과 지역 페이지——싱가포르, 도쿄, 서울, 홍콩, 버지니아, 실리콘밸리——로 실행층을 계약 가능한 환경에 두고, 엣지 프록시는 정책과 관측만 담당한다.
연결, 세션, 채널 이슈는 고객 센터에서 키워드로 검색하고, 시각적 분기에는 원격 데스크톱과 SSH/VNC 글을 함께 쓴다.
자주 묻는 질문
502일 때 프록시와 Docker 중 무엇을 먼저 보나요?
프록시 호스트에서 루프백 업스트림을 curl한다. 안 되면 Docker 네트워크 분기로. 플랜 비교는 Mac mini 대여 가격.
서브패스와 서브도메인은 어떻게 고르나요?
서브도메인이 제거 이슈를 덜 밟는다. 서브패스는 양쪽 베이스 URL을 맞춘다. 설치는 3플랫폼 설치 가이드로 버전을 맞춘다.
CDN 뒤에서 WS가 끊깁니다.
캐시 끄기, 유휴 타임아웃 연장, 제어용 서브도메인으로 CDN 우회. 채널 쪽은 Slack/Discord/Telegram 분기 글을 본다.
로그와 티켓은 어디로?
엔터프라이즈 변경은 고객 센터 티켓으로. 프로덕션 채팅에 Nginx 설정 절반만 흘리지 않는다.