크라우니 회복탄력성 · 모니터링 (2026-06-10)
개요
세션독립 관리시스템(워치독), monitor.crowny.org, :9100 admin 상주화, tiomta.com 외부 :443/:80 복구 — 4개 트랙 작업 결과와 메인루프 적용 런북. 모든 검증은 비파괴(라이브 무손상).라이브 재확인 시각 기준 상태(이 문서 작성 시점 실측):
| 대상 | 상태 | 비고 |
|---|---|---|
| gateway :8080 (한선씨 평문) | LISTEN(PID 1204) · 200 | apex tiomta.com Host 라우팅 200 |
| gateway :8443 (stunnel TLS) | LISTEN(PID 1202) · 200 | stunnel-live.conf, 로컬 tiomta TLS 200 |
| watchdog :9201 API | 200 · 22개 감시 · crowny-tiomta 포함 | PID 14762, launchd org.crowny.watchdog |
| monitor :9743 | 200 · LISTEN(PID 73285) | 고아 프로세스(소스/launchd 없음) — 개선본 미반영 |
| admin :9100 | 200(/health) · LISTEN(PID 1207) | 이미 상주 |
| tiomta.com :443 (외부) | 000 (timeout) — 다운 | 로컬 :443 리스너 부재. 단발 200 관측됐으나 3연속 재시도 전부 000 → 미복구 확정 |
| tiomta.com :8443 (외부) | 000 | 라우터가 8443으로 포워드 안 함 |
핵심: 보고서 작성 이후 라이브가 이동했다. T1(워치독 22개)·T3(admin 상주)는 이미 라이브 반영됨. T2(monitor 개선)·T4(:443 외부복구)만 미적용 → 메인루프 적용 대상.
T1 — 세션독립 서비스 관리(워치독) 고도화 [라이브 반영 완료]
/Users/ef/crowny-tiomta health=/api/health(200) → tiomta.com/Users/ef/crowny-mpti health=/api/health(200) → mpti.tiomta.com/Users/ef/crowny-amti health=/(200; /api/health 404 → 루트) → amti.crowny.org/Users/ef/crowny-abti health=/(200; /api/health 000 → 루트) → abti.crowny.org- startAPI(:9201) EADDRINUSE 핸들러: 'listen EADDRINUSE :9201 → Node 전체 크래시' 방어(API만 비활성, 감시 지속).
- status()에 backoffStep/nextRestartIn 노출 → /status·/history 가시화.
- 한선씨 동반본
서비스감시.한선(포트프로브/백오프지연/서비스점검/재기동 4함수) 컴파일+실행 검증
현재 라이브: /Users/ef/crowny-infra/crowny-stack.yaml에 crowny-tiomta 포함 확인, 워치독 PID 14762가
22개 감시 중 → 보고서의 '핫리로드 없음' 블로커는 해소됨(launchd 재기동이 이미 일어남).
관련 파일: watchdog.js, crowny-stack.yaml(buildWatchdogServices=22), 서비스감시.한선.
T2 — monitor.crowny.org 현황 + 개선 + 워치독 연동 [미적용 → 런북]
현황(개선 전)
라이브 :9743은 crownyc(한선씨) 프로세스로 200이나:- 소스 .한선 부재 + launchd 미등록 = 고아 프로세스(/tmp/crowny-monitor.toau 디스크 소실).
- UI가 구형 다크테마(#0f1117/파랑) — 클로드 밸런스 아님.
- 금융 6~7개 서비스만 모니터(전 서비스 아님).
- 워치독 복구 정보 전무.
개선
/Users/ef/crowny-gateway/한선게이트웨이/모니터개선.한선 (순수 한선씨 15KB, 빌드 .toau 동반).
- 클로드 밸런스 디자인(kraft #F4F2EC, 카드 #FBFAF7, 코랄 #D97757, Georgia, ✳, TOAU △○▽●).
- 전 서비스 실시간 상태:
gateway-status.json(38서비스) up/down 카드 + Ti/Om/Ta pill. - 워치독 자가복구:
watchdog-status.json에서 recovered/ti/ta/rate/마지막점검 + 미복구(failed 28건) 목록. - 신규 엔드포인트:
/api/services/api/recovery/api/status(Ti/Om/Ta 요약)/health. - 데이터 소스:
/Users/ef/.crowny-infra/logs/{gateway-status.json, watchdog-status.json}.
검증
그림자 포트 :19743(라이브 :9743 무단종료 없이) 컴파일+기동+헤드리스. 4 엔드포인트 JSON OK: /api/status={ti:38}, /api/services=38(up38), /api/recovery={rate:53.3, failed 28}, /health=200. 검증 후 그림자 종료, 라이브 :9743 내내 200.한선씨 함정 3건(우회 적용)
- 읽기()는 9MB+ append-only 로그 선두 ~9KB만 → tail 불가 → 정형 JSON 소스 사용.
- 글자() 바이트 재조립이 한글 멀티바이트 경계에서 NUL(0x00) 손상.
- Content-Length=글자수()는 한글 본문 잘림 → Connection:close만.
런북 (메인루프 — 자가복구 안전망 하)
bash# :9743 현재 고아 프로세스. 동일포트 순차교체(비파괴 불가).
cd /Users/ef/CrownyOS/crownyc
./hanseonc_high /Users/ef/crowny-gateway/한선게이트웨이/모니터개선.한선 \
> /Users/ef/crowny-gateway/한선게이트웨이/모니터개선.toau
OLD=$(lsof -nP -iTCP:9743 -sTCP:LISTEN -t); kill $OLD; sleep 1
nohup /Users/ef/CrownyOS/crownyc/crownyc run \
/Users/ef/crowny-gateway/한선게이트웨이/모니터개선.toau \
> /Users/ef/.crowny-infra/logs/crowny-monitor.log 2>&1 &
sleep 2; curl -s http://127.0.0.1:9743/api/recovery | head -c 120
# 영속화: crowny-stack.yaml에 crowny-monitor 추가(command=위 nohup) → 워치독 :9743 TCP 프로브 감시.
# 포트는 crowny-ports.sh로 등록됨(monitor.crowny.org→9743).
T3 — :9100 admin(관리자.한선) 상주 서버화 [라이브 반영 완료 · :9100 현재 200]
3가지 수정:
- 진입점 분기(~L291): 무조건 단위검증() →
ADMIN_SELFTEST=="1"일 때만 단위검증(),
- 포트 환경변수화: 수신포트결정() — 환경변수("GW_ADMIN_PORT") 정수 파싱, 미설정/<=0 → 9100.
- 인증서리로드() 재작성: 기존 curl POST :9100/certs/renew = 자기참조 데드락 →
pkill -HUP graceful reload. 라이브 stunnel(PID 53275)에 실제 HUP 전달 검증, :8443 유지.런처(게이트웨이기동.sh L87)는 이미 GW_ADMIN_PORT=9100 + ADMIN_SELFTEST 미설정 → 수정 소스가 자동 상주 분기.
cert-manager.sh 계약(ADMIN_API=:9100, GET /status→200, POST /certs/renew→200) 충족.
런북 (즉시 적용 — 위험변경: 게이트웨이 재기동 동반)
bashbash /Users/ef/crowny-gateway/한선게이트웨이/게이트웨이재기동.sh
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9100/health # 200
curl -s http://127.0.0.1:9100/status # engine:hanseon, port:9100
curl -s -o /dev/null -w "%{http_code}\n" -X POST http://127.0.0.1:9100/certs/renew # 200(stunnel HUP)
현재 :9100은 이미 200(상주 확인). 다음 재기동 사이클에 수정본이 안정 상주.
T4 — tiomta.com 외부접속 :443/:80 복구 [미적용 → 최우선 런북]
외부경로 결론
- tiomta.com → 공인 112.144.147.144 = 이 호스트 egress IP. LAN 192.168.219.153, 라우터 192.168.219.1(en1).
- 외부 :443/:80 = 000(timeout)(refused 아님) → 라우터가 공인 443/80을 내부로 포워드하나 내부 LISTEN 부재.
- 현재 라이브: stunnel :8443 + crownyc :8080만. :443/:80 비어있음(재확인됨).
- 로컬 :8080 H 라우팅 정상(apex Host→200), apex TLS도 ext 마스터 cert(SAN tiomta.com/www 포함) 종단 가능.
openclaw 정체(무관)
ai.openclaw.gateway/-gemini/-sonnet = crowny-genesis(/Users/ef/crowny-genesis/dist/index.js) AI 게이트웨이.
:18789/:18790/:18791(+내부18793) bind. :443/:80 절대 안 건드림. 양보협상 불필요.권한
macOS는 <1024 비루트 bind 제한 없음. 레거시 node가 동일 사용자 ef로 :443/:80 bind해 동작 = 증거. sudo 불필요.준비물(비파괴 생성 완료 · 검증됨)
stunnel_conf_gen.pylive443 모드 추가(live 모드 출력 byte-identical 회귀확인).stunnel-live-443.conf(697줄 · 25KB 확인됨): master[https443]+SNI슬레이브97, accept=0.0.0.0:443→connect 127.0.0.1:8080.
- :80 리다이렉트는
게이트웨이통합.한선이GW_PORT=80 GW_REDIRECT=1지원(L469~476, 301).
런북 (메인루프 전용 · 자가복구 안전망 하 · 기존 :8080/:8443 무손상)
bashcd /Users/ef/crowny-gateway/한선게이트웨이
# [1] 충돌 사전점검
lsof -nP -iTCP:443 -sTCP:LISTEN; lsof -nP -iTCP:80 -sTCP:LISTEN # 현재 둘 다 free
# [2] :443 stunnel 2차 인스턴스 기동(foreground=no 자체 데몬화)
/opt/homebrew/bin/stunnel /Users/ef/crowny-gateway/한선게이트웨이/stunnel-live-443.conf
sleep 1; lsof -nP -iTCP:443 -sTCP:LISTEN; tail -5 /tmp/stunnel-live-443.log
# [3] :80 → 301 리다이렉트 한선씨 인스턴스
export PATH="/Users/ef/CrownyOS/crownyc:$PATH"; export CROWNY_STD="/Users/ef/Downloads/CrownyTVM/std"
/Users/ef/CrownyOS/crownyc/hanseonc_high \
/Users/ef/crowny-gateway/한선게이트웨이/게이트웨이통합.한선 > /tmp/gwlive.toau
GW_PORT=80 GW_REDIRECT=1 nohup /Users/ef/CrownyOS/crownyc/crownyc run /tmp/gwlive.toau \
> /tmp/gw80.log 2>&1 &
echo $! > /tmp/gw80.pid; sleep 1; lsof -nP -iTCP:80 -sTCP:LISTEN
# [4] 검증 (로컬 → 외부)
curl -sk --resolve tiomta.com:443:127.0.0.1 https://tiomta.com:443/ -o /dev/null -w "local443=%{http_code}\n"
curl -s --resolve tiomta.com:80:127.0.0.1 http://tiomta.com:80/ -o /dev/null -w "local80=%{http_code}(301)\n"
curl -sk --max-time 10 https://tiomta.com/ -o /dev/null -w "EXTERNAL443=%{http_code}\n"
curl -s --max-time 10 http://tiomta.com/ -o /dev/null -w "EXTERNAL80=%{http_code}(301)\n"
# [4-대안A] 외부 여전히 000이면: 라우터 포워드 타겟이 8443일 가능성.
curl -sk --max-time 10 https://tiomta.com:8443/ -o /dev/null -w "ext8443=%{http_code}\n"
# → 8443=200이면 라우터 타겟=8443(이미 :8443 라이브가 받음, [2] 불필요). 라우터를 443→443으로 변경 권장.
# → 8443=000이면 라우터 포워드 자체 부재 → 라우터 admin에서 공인443→192.168.219.153:443 추가 필요.
# [5] 영속화 (검증 통과 후) — 게이트웨이기동.sh "go" stunnel 기동 직후 + 재기동.sh 정리 루프에 80/443 추가.
# [롤백] (외부영향 즉시 제거 · 라이브 :8443/:8080 무손상)
pkill -f stunnel-live-443.conf; [ -f /tmp/gw80.pid ] && kill -TERM "$(cat /tmp/gw80.pid)"
# [충돌처리] :443 선점 시 stunnel bind 실패('Address already in use') → 즉시 [롤백] 후 선점 PID 정체 파악.
# openclaw(:18789~91)는 :443 미사용이라 무관.
잔여 블로커
라우터 포워드 타겟(공인443→내부443 vs →8443)은 호스트 내부에서 확정 불가 → 외부 curl([4]/[4-대안A])로만 판별. pf NAT는 sudo 비번 필요로 미확인이나 라우터단 포워딩이라 호스트 pf 무관.메인루프 즉시 적용 우선순위
- T4 — tiomta.com :443 외부복구 (최우선, 사용자 외부접속 차단 상태). 런북 [1]→[2]→[3]→[4].
- T2 — monitor :9743 개선본 교체(고아 프로세스 → 영속화). 동일포트 순차교체.
- T3 — admin :9100: 이미 200 상주. 다음 게이트웨이 재기동 사이클에 안정화(능동 조치 불요, 모니터만).
- T1 — 워치독 22개: 이미 라이브 반영(PID 14762). 추가 조치 불요.
관련 파일
/Users/ef/crowny-gateway/한선게이트웨이/모니터개선.한선·모니터개선.toau/Users/ef/crowny-gateway/한선게이트웨이/stunnel-live-443.conf(697줄)/Users/ef/crowny-gateway/한선게이트웨이/stunnel_conf_gen.py(live443 모드)/Users/ef/crowny-gateway/한선게이트웨이/관리자.한선·게이트웨이통합.한선·게이트웨이기동.sh·게이트웨이재기동.sh/Users/ef/crowny-infra/crowny-stack.yaml(워치독 22서비스 SSOT) ·watchdog.js서비스감시.한선(T1 한선씨 동반)- 로그/데이터:
/Users/ef/.crowny-infra/logs/{watchdog.log, gateway-status.json, watchdog-status.json}