Gateway Health Monitor — 3대 false-alarm 근본 수정
날짜: 2026-05-27
대상: /Users/ef/crowny-gateway/scripts/health-monitor.sh
범위: 반복 발생 알람 3종의 근본 원인 식별 + 수정 + 검증
개요
5/27 새벽부터 10분 간격으로 동일한 false alarm 3종이 반복 발생. 일제 진단으로 근본 원인을 식별하고 수정. 진짜 장애 1건(code/agent 백엔드 down)도 함께 복구.
진단 결과 (시작 시점)
/Users/ef/.crowny-infra/logs/health-monitor.log 10분 주기 알람:
| 알람 | 빈도 | 1차 진단 |
|---|---|---|
| 포트 충돌 :9736 — crowny-avls 대신 / 실행 중 | 매 라운드 | False — PID 59072의 cwd가 / (데몬 fork 후) |
| SSL SAN 누락 ~170 도메인 — certbot 재발급 필요 | 매 라운드 | False — 단일 fullchain.pem만 검사 |
| 외부 접속 실패: code/agent/bank.crowny.org | 매 라운드 | bank는 즉시 해결, code/agent는 진짜 백엔드 죽음 |
근본 원인 + 수정
1. :9736 무한 충돌 (Bug A)
원인: health-monitor.sh:378-380 에서 lsof -p $pid | grep cwd 로 작업 디렉토리 비교.
- node 데몬은 fork 후
cwd를/로 변경 → 모든 비교 FAIL - kill → 재시작 → 새 PID도 동일하게 cwd=/ → 10분 후 또 충돌 알람 → 무한 루프
scripts/health-monitor.sh:378-382): cwd → ps -o command= (cmdline 매칭)bash# 변경 전
local cwd=$(lsof -p "$pid" 2>/dev/null | grep cwd | awk '{print $NF}')
if [ -n "$cwd" ] && ! echo "$cwd" | grep -q "$expected_dir"; then
# 변경 후
local cmdline=$(ps -p "$pid" -o command= 2>/dev/null)
if [ -n "$cmdline" ] && ! echo "$cmdline" | grep -q "$expected_dir"; then
검증:
- PID 59072 cmdline =
/opt/homebrew/bin/node /Users/ef/crowny-avls/server.js→ "crowny-avls" 포함 ✓ - 재시작 후 :9736 알람 0건 확인
2. SSL SAN false-alarm 폭주 (Bug B)
원인: check_ssl_san() 가 crownybus.com/fullchain.pem 단일 인증서만 검사. 게이트웨이는 ssl.js 에서 crownybus.com, crownybus.com-ext, real-crowny 3개 인증서를 합쳐서 도메인별 SecureContext 로드. 비교 기준이 1/3 → 나머지 2/3에 포함된 도메인이 모두 "누락" 판정.
수정 (scripts/health-monitor.sh:337-372): certbot/live/*/fullchain.pem 전체를 순회해 SAN을 합쳐서 비교.
bashfor sub in "$live_dir"/*/; do
cert="${sub}fullchain.pem"
sans=$(openssl x509 -in "$cert" -noout -ext subjectAltName ...)
cert_sans="${cert_sans}${sans}"$'\n'
done
cert_sans_sorted=$(echo "$cert_sans" | sort -u)
검증:
- 알람 메시지에
(N개 인증서 합산)라벨 추가 → 어떤 모드인지 명시 - 첫 라운드: 누락 도메인 145→53개로 감소 (잔여는 진짜 SAN 미포함 — certbot 재발급 대상)
3. code/agent 백엔드 진짜 down (Bug C — 실제 장애)
원인:
/Users/ef/crownycode-remote/gateway.js(포트 9900) 죽음/Users/ef/crownycode-remote/agent/server.js(포트 9901) 죽음- 게이트웨이의 Trident가 Ta(장애)로 표시 → 503 응답
- health-monitor SERVICES 목록에 code/agent 미등록 → 자동 복구 불가
nohup node 로 재시작.bashcd /Users/ef/crownycode-remote && nohup node gateway.js >> .../crowny-code-9900.log 2>&1 &
cd /Users/ef/crownycode-remote/agent && nohup node server.js >> .../crowny-agent-9901.log 2>&1 &
검증:
- 9900/9901 LISTEN 확인
- 30초 후 Trident 자동 복구 탐색 → 게이트웨이 경유 200 OK
작업 후 상태
- :9736 알람: 12:19:29 이후 0건 ✓
- SSL SAN 알람: "3개 인증서 합산" 모드 동작, 잔여 누락 도메인 53개 (진짜 미포함 — 추후 certbot 작업)
- code/agent: 게이트웨이 경유 200 OK ✓
- 36 서비스 중 28~31 UP (점진 복구 중 — enterprise/downloads/market 등 자동복구 진행)
잔여 이슈 → 후속 4작업 진행
(1) code/agent SERVICES 등록 — 완료
scripts/health-monitor.sh:56-57 에 두 줄 추가:
bash"code|9900|http://127.0.0.1:9900/health|node|false|$NODE /Users/ef/crownycode-remote/gateway.js"
"agent|9901|http://127.0.0.1:9901/health|node|false|$NODE /Users/ef/crownycode-remote/agent/server.js"
검증: gateway-status.json 에 "code":"up", "agent":"up" 표시. 서비스 수 36→38.(2) SSL SAN 51개 certbot 재발급 — Plan 완료 (실 발급은 사용자 승인 후)
핵심 발견: 누락 53개 중 51개가 정상 도메인, 10개는 yaml 설정 오류(pay, crns, crowny-dist, remote*, 티옴타작업소 등 도메인 suffix 누락).선결조건 발견: 누락 51개 중 44개가 NXDOMAIN — hosting.kr DNS A 레코드 부재.
- HTTP-01 챌린지는 도메인이 게이트웨이 IP로 resolve되어야 가능. NXDOMAIN 상태에선 챌린지 실패.
- 우선 hosting.kr 패널에서 와일드카드
*.crowny.org,*.tiomta.com,*.crownybus.comA 레코드 추가 필요 (가장 빠른 방법).
bashsudo certbot certonly \
--config-dir /Users/ef/crowny-data/certs/certbot \
--webroot --webroot-path /Users/ef/crowny-gateway/webroot \
--cert-name crownybus.com-ext --key-type ecdsa \
--allow-subset-of-names --expand --dry-run \
$(xargs -a /tmp/missing-sans.txt -I D printf '%s\n' '-d D')
위험: hosting.co.kr NS의 간헐적 CAA SERVFAIL (Phase 4 이슈) — crowny.org. CAA 0 issue "letsencrypt.org" 선제 추가 권장.
(3) 외부 접속 점검 실패 — 진단 완료
근본 원인: 라우터(192.168.219.1) NAT 포트포워딩 부재 또는 끊김.- 호스트: 80/443/8080/8443 모두 LISTEN 정상 (PID 27394 게이트웨이)
- LAN IP: 192.168.219.153, 공인 IP: 112.144.147.144 (KT)
- 외부 IP의 80/443에 즉시 Connection refused (filtering이면 timeout이 나야 함)
- DNS 해석 OK, 호스트 LISTEN OK → 라우터 NAT가 단일 후보
http://192.168.219.1 관리 페이지에서
- 외부 80 → 192.168.219.153:80 매핑
- 외부 443 → 192.168.219.153:443 매핑
- 활성/대상 IP 일치 확인 (DHCP 변경 시 어긋남)
(4) health-monitor 한선씨 동반본 포팅 — 완료
scripts/health-monitor.한선 에 추가:
함수 트림(s)— 개행/공백 제거 (한선씨 네이티브)함수 포트충돌검사()— bash의check_port_conflicts한선씨 등가함수 SSL_SAN검사()— bash의check_ssl_san한선씨 등가- 메인 루프에 두 함수 호출 추가
가져오기 "문자열.한선"추가
${var}셸 변수 보간이 한선씨 토크나이저에 식별자로 잡힘 → xargs로 회피- 다른 라이브러리에 정의된 함수(예:
시작확인)가 가져오기에도 호출 안 될 때가 있음 →포함()>= 0 비교로 동등 처리
- 컴파일 성공: 706KB toau, 25,218 큐브
- 단위 테스트: 한선씨 측 SSL_SAN 검사가 53개 누락 도메인 동일 감지
작업 후 최종 상태
| 항목 | 상태 |
|---|---|
| :9736 무한 충돌 알람 | ✓ 해결 (cmdline 매칭) |
| SSL SAN false-alarm 폭주 | ✓ 해결 (3개 인증서 합산) |
| code/agent 백엔드 down | ✓ 복구 + 자동복구 등록 |
| code/agent 게이트웨이 경유 | ✓ 200 OK |
| 한선씨 동반본 포팅 | ✓ 충돌검사·SSL SAN 검사 추가 |
| SSL SAN 진짜 누락 51개 | ✅ certbot 발급 완료 — ext 인증서 11→61 SAN |
| 외부 접속 실패 0/5 | ✅ 라우터 룰 ON + 와일드카드 DNS 적용 → 5/5 회복 |
후속 작업 결과 (추가)
certbot 재발급 — 완료
- DNS 와일드카드
*.crowny.org/*.tiomta.com/*.crownybus.com추가 (사용자) → 44개 NXDOMAIN 일괄 해소 - 라우터 80→8080, 443→8443 포트포워딩 룰 ON 확인 (사용자)
- certbot dry-run 61 SAN 성공 → 실 발급 성공 (만료 2026-08-25)
- 게이트웨이 재시작 시 새 ext 인증서 SNI 매핑 자동 적용 (
docs.crowny.org subjectAltName matched)
/certs/renew 와 /reload admin API는 SNI 컨텍스트 재빌드를 안 함. SIGHUP는 메인 프로세스 종료만 시켜 launchd가 자동 재기동. 새 인증서 적용엔 완전 재시작이 필요. 추후 ssl.js의 contexts 재로드 메소드 추가가 깔끔.일제 진단 결과 (154 도메인)
| 분류 | 개수 |
|---|---|
| 🟢 정상 (외부 200) | 52 |
| 🟡 DNS OK / upstream 미가동 | 90 (대부분 운영 안 하는 서비스) |
| 🔴 NXDOMAIN (yaml placeholder 11) | 11 (gateway.yaml 정리 대상) |
| ⚫ 잘못된 IP | 0 |
academy / finance 확인
- academy.crowny.org: 백엔드 :9865 LISTEN 활성, 외부/내부 200 OK
- finance.crowny.org: PID 92591 node proxy.js :9754, 5시간 39분 안정 가동, 외부/내부 200 OK
gateway.yaml 정리 권장 (suffix 없는 placeholder 11)
book-agent → book-agent.crowny.org (진짜 도메인 의도?)
cif-editor → cif-editor.crowny.org
crns → crns.crowny.org
crowny-dist → dist.crowny.org
cycle → cycle.crowny.org
pay → pay.crowny.org
remote → remote.crowny.org
remote-agent → remote-agent.crowny.org
remote-pty → remote-pty.crowny.org
reward-ui → reward-ui.crowny.org
value → value.crowny.org
티옴타작업소 → xn--... (Punycode IDN 변환)
각 항목별로 suffix 추가하면 와일드카드 DNS로 즉시 해결되고, 다음 certbot 갱신 시 SAN에 자동 포함됨.
관련 파일
/Users/ef/crowny-gateway/scripts/health-monitor.sh(수정)/Users/ef/crowny-gateway/lib/ssl.js(참조)/Users/ef/crowny-data/certs/certbot/live/(3개 인증서 디렉토리)/Users/ef/.crowny-infra/logs/health-monitor.log(검증)/Users/ef/crownycode-remote/gateway.js(재시작)/Users/ef/crownycode-remote/agent/server.js(재시작)