Matrix
한 줄 소개: AXE Labs 내부 인프라 (Docker 컨테이너 · HTTP 엔드포인트 · Cloudflare tunnel · 디스크) 의 health 를 1 분 주기로 수집하여 (a) axe.axelabs.ai/matrix 상태 보드, (b) acked_at IS NULL alert 큐, (c) Blueprint 에이전트가 MCP 5 도구로 조회 — 의 3 가지 surface 로 노출하는 첫 Rust 서비스 (D-matrix-1).
기술 스택
| 항목 | 값 |
|---|---|
| 언어 | Rust 2024 edition (toolchain rust:1.95-slim) |
| HTTP framework | axum 0.8 + tower-http (CORS) |
| Async runtime | tokio 1 (full) |
| DB | PostgreSQL 16 (alpine, ICU ko-KR) + sqlx 0.8 (runtime-tokio + tls-rustls) |
| Docker API | bollard 0.18 (container health 조회) |
| HTTP client | reqwest 0.12 (rustls, 5s timeout) — endpoint probe |
| 인증 | jsonwebtoken 9 (HS256 JWT, MATRIX_JWT_SECRET) — 현재 router 미부착, known-gaps 참조 |
| 스케줄링 | tokio-cron-scheduler 0.13 + tokio sleep loop |
| 로깅 | tracing + tracing-subscriber (env-filter + json formatter) |
| Migration | 코드 인-라인 (db.rs migrate(), CREATE TABLE IF NOT EXISTS) |
소스: /Users/axe/matrix/src/ (~600 LOC, 6 modules: api · auth · collector · config · db · mcp)
포트
| 포트 | 용도 |
|---|---|
| 3901 | PostgreSQL 16 (matrix-postgres) |
| 3910 | MCP HTTP blue (matrix-mcp-blue, alias matrix-mcp active) |
| 3911 | MCP HTTP green (matrix-mcp-green, passive) |
| 3912 | axe-matrix-proxy (Caddy blue/green selector, 127.0.0.1 bind only) |
cloudflared origin → 외부 https://axe.axelabs.ai/matrix + https://axelabs.ai/matrix (둘 다 같은 path 라우팅). matrix.axelabs.ai 서브도메인은 미등록 — DNS resolve 실패. 정식 경로는 axe.axelabs.ai/matrix.
3 가지 surface
- MCP (
POST /matrix/mcp) — JSON-RPC 2.0 over HTTP, 5 tools. Blueprint / Claude 에이전트가 도구로 호출 - REST (
GET /matrix,/matrix/api/status,/matrix/api/alerts) — 상태 보드 (인증 없음, 의도된 공개) - Health probe (
GET /health,/health/ready) — Docker healthcheck + 외부 모니터링
/matrix/mcp는 코드상auth.rs::auth_middleware정의되어 있으나api.rs::router()에 부착되지 않음. 현재 anonymous 호출 가능. B-matrix-mcp-auth-enforce 참조.
MCP Tools (5 개)
src/mcp.rs:91-150 의 handle_tools_list() 기준. protocolVersion: 2025-03-26, serverInfo.name: "matrix", serverInfo.version: env!("CARGO_PKG_VERSION") (현재 0.1.0).
| Tool | 입력 | 설명 |
|---|---|---|
get_status | — | 가장 최근 collector cycle 의 전체 health 보고 (in-memory last_check). 한 번도 안 돈 직후엔 "no check results yet" |
get_service_history | service (string, required), hours (int, default 24) | 특정 서비스의 시계열 — check_results.report JSONB 에서 해당 name 의 status/detail 추출 (최근 100 rows) |
list_alerts | include_acked (bool, default false) | unacked alert 50 개 (or 전체 50). UUID + service + severity + message + created_at + acked_at/by |
acknowledge_alert | alert_id (UUID, required), acked_by (string, default "operator") | UPDATE alerts SET acked_at = now(), acked_by = $1 WHERE id = $2 AND acked_at IS NULL — 이미 ack 된 항목은 no-op |
get_uptime_report | days (int, default 7) | 기간 내 모든 cycle 의 per-service pass/total 카운트 + uptime% (소수점 2 자리) |
REST endpoints
| 메서드 | 경로 | 인증 | 설명 |
|---|---|---|---|
| GET | /health | — | {"status":"ok","service":"matrix"} (DB 미점검) |
| GET | /health/ready | — | {"status":"ok","db":"connected"} 또는 503 + {"db":"<err>"}. Docker healthcheck 가 사용 |
| GET | /matrix | — | landing (상태 보드, 미구현 placeholder 가능성) |
| GET | /matrix/api/status | — | 최근 cycle 의 JSON 전체 — get_status MCP 와 동일 데이터 |
| GET | /matrix/api/alerts | — | unacked 20 개 alert |
| POST | /matrix/mcp | — (의도는 JWT) | MCP JSON-RPC. initialize / tools/list / tools/call 처리 |
데이터 모델
src/db.rs:14-39 의 인-라인 migration (CREATE TABLE IF NOT EXISTS). 3 테이블 + 2 인덱스.
| 테이블 | 컬럼 | 역할 |
|---|---|---|
check_results | id UUID PK · ts TIMESTAMPTZ · duration_ms INT · overall TEXT (pass/fail) · report JSONB | collector cycle 의 전체 보고서 (모든 service check 결과 array 포함) |
services | name PK · svc_type · config JSONB · created_at | (현재 미사용 — 향후 동적 등록용) |
alerts | id UUID PK · service · severity (default error) · message · created_at · acked_at · acked_by | failure 1 회 발생 시 INSERT, 동일 서비스의 unacked alert 이 있으면 no-op (중복 방지) |
인덱스: idx_check_results_ts (DESC), idx_alerts_unacked (partial WHERE acked_at IS NULL).
Collector — 무엇을 보는가
src/collector.rs::run_loop() — MATRIX_CHECK_INTERVAL 초마다 (default 30, D-matrix-2 에서 60→30), run_check() 가 5 종류 점검 병합:
| 종류 | 함수 | 대상 | 판정 |
|---|---|---|---|
| Docker container | check_docker | bollard 로 all=false (실행 중) 컨테이너 list. status 문자열에 healthy / unhealthy 포함 검사. matrix- 접두는 자가 모니터링 회피로 skip | unhealthy = fail, healthy or running = pass |
| HTTP endpoint | check_http | 2 개 — blueprint-http (host:3100/api/health) + frame-mcp-http (host:3710/health, alive-only). cortex-fe/cortex-be 는 개발 중이라 제거 (commit 96cf758, 재가동 시 재활성) | 상태코드 일치 = pass; frame 만 응답 있으면 pass |
| Cloudflare tunnel | check_tunnels | 3 개 — tunnel-artemis, tunnel-blueprint, tunnel-mysrt (*.axellc.com) | 200/301/302 = pass, 그 외 = warn, unreachable = fail |
| Disk | check_disk | df -h / 의 root 디스크 사용률 | ≥90% = warn |
| WAN/인터넷 | check_wan | 3 프로브 동시(tokio::join!) — wan-gateway (공유기 ICMP), wan-internet (MATRIX_WAN_TARGET ICMP, RTT+손실%), wan-dns (MATRIX_DNS_HOST 해석 시간). D-matrix-2 | unreachable = fail. 귀책 판별: gateway ↑ + internet ↓ ⇒ ISP/WAN fault (warning 발생), gateway ↓ + internet ↓ ⇒ 댁내 링크/WiFi |
호스트 도달은 모두 host.docker.internal 경유. failure 시 create_alert() 가 동일 서비스의 unacked alert 가 없을 때만 INSERT (중복 방지). cycle 결과는 항상 check_results 에 INSERT.
WAN 프로브 (D-matrix-2):
wan-*결과는 기존check_resultsJSONB 에 그대로 들어가 별도 스키마 변경 없이get_service_history/get_uptime_report/ 상태 보드 / alert 에 자동 노출. ICMP 는 컨테이너에cap_add: NET_RAW+ 런타임 이미지의iputils-ping으로 권한상승 없이 가능 (Docker Desktop NAT 통과 + 공유기/외부 도달 검증 2026-06-03). 게이트웨이 IP 는 노드별로 다르므로MATRIX_LAN_GATEWAYenv 로 주입.
함정 (2026-05-26 발견 → 같은 날 fix):
blueprint-httpURL 이:3110(미 listening) 으로 25 분+ 연속 FAILED 누적. 정정::3100/api/health(Blueprint Next.js dev). 동일 세션에서cortex-fe/cortex-be도 검증 — cortex backend (:3210) 는 실제 down, cortex frontend (:3200) 는 listening 하지만 root path 빈 응답 → 두 항목은 valid alert (cortex 측 점검 별도 필요). B-matrix-collector-port-fix ✅
환경 변수
src/config.rs::Config::from_env() 기준. .env.local (env_file) 으로 vault → 컨테이너 dump (D-ops-18 패턴).
MATRIX_PORT=3910 # default 3910
MATRIX_DATABASE_URL=postgres://matrix:<pw>@postgres:5432/matrix
MATRIX_DB_PASSWORD= # compose 가 ${MATRIX_DB_PASSWORD:?required}
MATRIX_JWT_SECRET= # default "dev-secret-change-me" — production 미설정 시 위험
MATRIX_CHECK_INTERVAL=30 # 초 (D-matrix-2: 60→30, 끊김 해상도 향상)
MATRIX_CUSTOMER_ID=axe # multi-tenant 마커
MATRIX_DEPLOY_COLOR=blue|green # blue/green 식별
MATRIX_LAN_GATEWAY=192.168.55.1 # wan-gateway 프로브 대상 (공유기 IP, 노드별 상이)
MATRIX_WAN_TARGET=1.1.1.1 # wan-internet 프로브 대상 (공인 anycast)
MATRIX_DNS_HOST=google.com # wan-dns 해석 테스트 호스트
MATRIX_LAN_GATEWAY/MATRIX_WAN_TARGET/MATRIX_DNS_HOST는 비밀이 아니라 노드별 설정값 — secrets 표/vault 등재 불필요 (default 존재). 단MATRIX_LAN_GATEWAY는 DHCP 로 바뀔 수 있어 노드 셋업 시 확인 (D-matrix-2).
/architecture/secrets 의 service secrets 표 등재 (matrix .env.local = DB password + JWT secret + console API token 3 종).
Blue/green 운영
matrix-mcp-blue와matrix-mcp-green가 동일 image (compose 의build: .) 로 동시 실행. blue 만matrix-mcpnetwork alias 보유 →axe-matrix-proxy(Caddyfile 의reverse_proxy matrix-mcp:3910) 가 항상 blue 로 forward.- swap = compose 의 alias 를 green 으로 옮긴 후
docker compose up -d --no-deps matrix-mcp-green→ 검증 → blue 도 업데이트. frame · hive 와 동일 패턴. - 현재 상태 (2026-05-26): 두 컨테이너 동일 코드 (build 동시), 둘 다 healthy, 3 일 가동.
운영 노트 · 알려진 함정
Git 미커밋✅ —f73492d(initial) +48a301b(fix) 두 commit 으로 history 회복 (2026-05-26).Stale build (2026-05-23)✅ —matrix_info함수 미정의 (E0425) 였던 게 root cause. 같은 날 stub 추가 + 무중단 rebuild.JWT 미적용✅ —/matrix/mcp에middleware::from_fn(auth_middleware)부착 (commit96cf758). REST + health 는 anonymous 유지 (의도된 공개 status board). 검증: no-auth POST → 401 “missing bearer token”, REST → 200. production 호출 client 0 (access log 0 + Blueprint repo 미참조) 확인 후 안전 부착.- 자가 모니터링 회피: collector 가
matrix-접두 컨테이너를 skip. matrix-postgres 도 skip 됨 — 의도된 단순화, 그러나 DB 가 죽으면/health/ready자체가 503 떨어지므로 외부 healthcheck 로 보완. - 39xx 범위 공유:
axelabs회사 홈 (3900) 과 matrix (3901/3910/3911/3912) 가 같은 범위에서 공존. CLAUDE.md / /ops/inventory#포트-할당 에 명시. 부수 발견 — cortex 측 valid alert✅ resolved by removal — cortex 가 개발 중이라 collector endpoint list 에서 cortex-fe / cortex-be 제거 (commit96cf758, src/collector.rs:181). 재가동 시 다시 활성화. 누적 unacked alert 2 row (acked_by='cortex-removed-from-collector-2026-05-26') ack 처리.
관련 문서
- D-matrix-1 — Rust + native MCP 채택 결정
- /ops/backlog —
B-matrix-*시리즈 (deploy, blueprint connector, console retire, rebuild, git init, auth enforce, collector port fix) - /architecture/secrets — matrix
.env.local3 secrets - /architecture/artifacts —
[email protected]schema 노출 - /services/blueprint — matrix MCP 의 client