Topology · 네트워크
외부 경계 — Cloudflare
모든 외부 트래픽은 Cloudflare 의 anycast 망을 통해 도달합니다.
| 구간 | 도메인 / 호스트 | 처리 |
|---|---|---|
| DNS | axelabs.ai zone (Cloudflare) | A/CNAME → Cloudflare proxy IPs |
| 전송 보안 | Cloudflare → cloudflared (HTTPS) | mTLS connector |
| 터널 | axelabs-tunnel (Docker, ID d8efecdd-2c3f-42de-9925-501433e21394) | tunnel ingress |
| origin | host.docker.internal:{port} | per-service routing |
cloudflared config 위치: /Users/axe/.axe/tunnels/axelabs/config.yml
Tunnel ingress 규칙
tunnel: d8efecdd-2c3f-42de-9925-501433e21394
ingress:
- hostname: axe.axelabs.ai
path: ^/frame(/.*)?$
service: http://host.docker.internal:3712 # axe-frame-proxy
- hostname: axe.axelabs.ai
path: ^/vault(/.*)?$
service: https://host.docker.internal:8222 # axe-vault-caddy
- hostname: admin.axelabs.ai
service: http://axe-caddy:80 # operator console
- hostname: axe.axelabs.ai
service: http://host.docker.internal:3100 # blueprint apex
- service: http_status:404 # default deny⚠️ 함정 — cloudflared SIGHUP 미지원
[1m[31mcloudflared 는 SIGHUP graceful reload 를 지원하지 않습니다.[0m검증된 사실 (2026-05-15): docker kill -s HUP axelabs-tunnel 실행 시 프로세스가 종료됩니다. config 변경 = 컨테이너 재시작 = 5초 다운타임.
대응: 변경 잦은 부분 (frame upstream, blue/green swap) 을 cloudflared config 에서 분리하고 host-side proxy 뒤로 이전.
→ 결과: cloudflared 는 host.docker.internal:3712 한 줄만 알고, blue/green swap 은 그 proxy 내부에서 처리. cloudflared 재시작 없음.
Host-side proxy 패턴 (axe-frame-proxy)
axe-frame-proxy = Caddy reverse-proxy 컨테이너. host port 3712 노출. 단일 책임: /frame/* 트래픽을 docker network 위의 frame-mcp alias (blue 또는 green 중 active 쪽) 로 라우팅. blue/green swap = alias 이동 + Caddy graceful reload (SIGHUP 지원, cloudflared 와 달리). frame 컨테이너의 build/recreate 와 무관하게 cloudflared 안정.
cloudflared (axelabs-tunnel)
│
↓ HTTP /frame/* → host.docker.internal:3712
│
↓
┌──── axe-frame-proxy (Caddy) ────┐
│ │
│ /frame/* → upstream (선택) │
│ │ │
│ ↓ │
│ frame-mcp-blue :3710 │ ← network alias `frame-mcp`
│ frame-mcp-green :3711 │ (blue/green swap = alias move)
│ │
└─────────────────────────────────┘핵심: cloudflared 는 axe-frame-proxy 만 알고, blue/green 의 실제 컨테이너 이름·포트는 모릅니다. swap 은 docker network alias 이동으로 처리 (axe deploy frame axe --apply).
Docker 네트워크 — artemis_default
axelabs 플랫폼의 모든 컨테이너 (axelabs-tunnel, axe-frame-proxy, frame-mcp-blue/green, blueprint-app 등) 는 artemis_default 외부 docker 네트워크 위에서 통신합니다.
# 검증
docker network inspect artemis_default | grep '"Name"'frame docker-compose.yml 에서:
networks:
artemis_default:
external: true # 별도 docker 명령으로 생성된 망에 합류포트 할당 (CLAUDE.md SSOT)
| 범위 | 프로젝트 |
|---|---|
| 31xx | Blueprint |
| 32xx | Cortex |
| 33xx | Artemis |
| 34xx | Distributa |
| 35xx | Kolon Discussion |
| 36xx | mysrt |
| 37xx | frame |
전체 포트 테이블은 /Users/axe/CLAUDE.md 가 SSOT. 새 서비스 추가 시 반드시 비어 있는 범위 확인.
⚠️ 함정 모음
| 함정 | 결과 | 회피 |
|---|---|---|
| cloudflared SIGHUP 직접 호출 | process 종료, 다운타임 | host-side proxy 뒤로 |
| frame 컨테이너 이름을 cloudflared 에 직접 명시 | blue/green swap 불가 | network alias 사용 |
| path strip 기대 (cloudflared) | 라우터가 prefix 못 찾음 | 각 서비스에 /frame prefix mount |
2-level subdomain (frame.axe.axelabs.ai) | Cloudflare Universal SSL 무료 미커버 | 1-level + path |
axellc.com 으로 platform traffic | corporate ↔ platform 경계 혼탁 | 평행 운영, 신규는 axelabs.ai only |
artemis_default external network 사전 부재 (신규 customer macmini) | axe deploy 시 network artemis_default declared as external, but could not be found → compose up fail | onboard step 에 docker network create artemis_default pre-step (또는 axe deploy 자체에 _svc_step_network 빌트인 — 2026-05-25 이후 적용 ✅, trap #17 of B-onboard-d-day-traps-2026-05-25) |
상세 결정 근거는 DECISIONS §3 D-config-13 참조.