Skip to Content

배포 협의

귀사 macmini 에 AXE Labs 스택을 배포하는 일정과 사전 요구사항.

사전 요구사항 (D-7)

#항목책임
1macmini 1대 (M2/M3, 16GB+ RAM, 512GB+ SSD)귀사 (구매)
2항상 켜진 상태 + 인터넷 안정 (유선 권장)귀사
3Tailscale 가입 + macmini 가 tailnet 에 합류귀사 IT
4운영자의 Tailscale SSH key 허용귀사 IT
5Microsoft 365 tenant + 3개 app 등록귀사 IT
6{customer}.axelabs.ai 도메인 검증귀사 IT + 액스코퍼레이션 주식회사 (DNS)
7client_secret VALUE 안전 채널 전달귀사 IT

위 7 개 완료 = D-day 작업 진행 가능.

D-day 작업 (운영자 측, 4시간)

운영자가 axe onboard {customer} --apply 실행. 18-step 자동화:

Step작업다운타임
1Tailscale status check0s
2customer registry 확인0s
3SSH probe (macmini reachable?)0s
4Cloudflare tunnel credential push0s
5-9cloudflared launchd 설정0s
10frame docker preflight + git pull~30s
11-16frame docker-compose bootstrap~5min (이미지 빌드)
17health check0s
18운영자 알림

총 ~4시간 (이미지 빌드 + 첫 데이터 sync 포함).

D+1 (검증)

  • 운영자가 직접 첫 로그인 검증
  • 귀사 admin 사용자 (ADMIN_EMAIL) 에게 권한 부여
  • 검증 메일 발송

D+2 ~ (운영)

  • 귀사 직원 onboarding 시작
  • 각자 신규 직원 온보딩 따라 setup
  • 1차 helpdesk = 귀사 IT (URL/secret 확인 등), 2차 = 운영자 (서버 측)

도입 후 귀사 macmini 의 실 컨테이너 구성

axe onboard {customer} --apply + axe deploy blueprint/hive {customer} 가 끝난 뒤 귀사 macmini 에 떠 있는 컨테이너 목록 (docker ps 결과 — realchoice 예시):

realchoice-macmini (M2+, 16GB+, Tailscale 메시, 절전 OFF) ├ axelabs-realchoice-tunnel (cloudflared, customer 별 독립 tunnel — origin 한 줄만) ├ frame-postgres :3700 ├ frame-mcp-blue :3710 / frame-mcp-green :3711 (blue/green, 무중단 swap) ├ axe-frame-proxy :3712 (Caddy blue/green selector) ⚠️ axe- prefix ├ frame-worker (cron + match_pending_sweep) ├ hive-postgres :3800 ├ hive-mcp-blue :3810 / hive-mcp-green :3811 (blue/green) ├ axe-hive-proxy :3812 (Caddy blue/green selector) ⚠️ axe- prefix ├ blueprint-postgres ├ blueprint-app :3100 + WebSocket :3101 (blue, dev/build 시 수십초 다운) ├ blueprint-app-green (passive, B-bp-bluegreen 후 활성) ├ blueprint-mcp-blue :3152 / blueprint-mcp-green :3153 (read-only MCP, blue/green) ├ stream-mcp :8780 (귀사 기존 자산, manifest 정렬) ├ magnet-mcp :8770 (귀사 기존 자산, manifest 정렬) ├ axe-vaultwarden (Vaultwarden core) ⚠️ axe- prefix └ axe-vault-caddy :8222 (Vaultwarden front + OIDC) ⚠️ axe- prefix

컨테이너 이름 컨벤션 — 정확히 무엇이 customer-aware 인가

패턴예시customer 식별
customer-prefix 적용 (axelabs-{customer}-...)axelabs-realchoice-tunnel✅ — axe onboard (_render_cloudflared_config, axe CLI line 2829) 가 customer ID 박음. axe customer 는 axelabs-axe-tunnel 이 아니라 axelabs-tunnel (historical)
customer-agnostic ({service}-...)frame-postgres, hive-mcp-blue, blueprint-app, blueprint-mcp-green✅ — customer-per-macmini 격리로 같은 host 에 다른 customer 가 없어 충돌 위험 0. macmini hostname (realchoice-macmini) 으로 식별
⚠️ historical axe- prefix 잔존axe-frame-proxy, axe-hive-proxy, axe-vaultwarden, axe-vault-caddy❌ — frame/docker-compose.yml:197, hive/docker-compose.yml:124, vault/docker-compose.yml:29/66container_nameaxe- 박혀 있음. realchoice macmini 에서도 컨테이너 이름은 axe-.... customer-per-macmini 격리상 충돌은 없지만 misleading. backlog 등재: B-container-name-customer-prefix

⚠️ 즉 받은 도식의 axe-frame-proxy / axe-vault-caddy 가 “왜 axe-?” 의문은 정확함 — 실제로 그 이름 그대로 떠 있는 게 맞음 (historical artifact). axelabs-tunnel 만 customer-prefix 누락 (이건 axe customer 전용 이름이라 realchoice 측은 axelabs-realchoice-tunnel).

향후 일반화는 B-container-name-customer-prefix — compose 의 container_name${CUSTOMER_PREFIX}- 변수화. 실 운영 영향 없어 우선순위 中.

함정

사전 요구사항 단계 (D-7 ~ D-1)

함정결과회피
Tailscale 미설치운영자 push deploy 불가D-7 까지 설치 + key 등록
macmini sleep 모드새벽 backup 실패”절전 안 함” 설정
도메인 검증 누락Application ID URI 등록 거부검증 후 app 등록
client_secret 분실재발급 + 운영자 측 swap회신 즉시 안전 보관

D-day 18-step 자동화 단계 (2026-05-25 트루비아 측 발견 — B-vault-d-day-traps-2026-05-25 + B-onboard-d-day-traps-2026-05-25)

함정step증상회피
Private GitHub repo clone 인증 promptclone (step 10/11)axelabs-ai/frame · axelabs-ai/hive clone 시 PAT prompt → SSH 자동 deploy hang운영자 임시 PAT 등록 후 customer 측 team add (D-dev-platform-2)
docker network artemis_default 사전 부재network create (pre step 11)external: true declared network not found → compose up faildocker network create artemis_default (axe deploy_svc_step_network 빌트인 ✅, 2026-05-25 이후 자동)
Blueprint MCP app (4번째 Entra app) 등록 누락bootstrap.sh 또는 registryApp #4 미등록 → MCP OAuth 시 redirect 실패bootstrap.sh App #4 추가 (B-axelabs-bootstrap-blueprint-mcp-app 후속)
external volume 6개 (blueprint 측) 사전 부재docker compose upexternal: true declared volume not foundcompose 의 external 제거 또는 pre-step docker volume create (R6 후속)
~/.axe/customers.yaml 이 directory 로 잘못 사전 생성onboard stepfile write failonboard step 의 mkdir parent only 정정
ADMIN_TOKEN argon2 hash $ interpolationvault env_file (step 11)compose v2 yaml expansion 으로 $ segment 가 빈 값 — vault admin lockout$$$ escape (axe secret pullescape_dollar flag 빌트인 ✅)
Timshel vault image wget 없음compose healthcheckwget: command not found → unhealthy 무한 루프healthcheck → curl 변경
sso_nonce column 이름 (code_verifierverifier)vault recovery SQLcolumn not foundrunbook 정정 ✅ (PostgreSQL/SQLite backend 분기)
bw CLI 2026.4+ Timshel SSO 호환성partner setup (bw login)“Master password unlock data was not found”bw 2025.7.0 pin: npm install -g @bitwarden/[email protected] (또는 axe.2 patch 적용 vault image)
bw data dir keychain restorebw loginrm -rf "~/.config/Bitwarden CLI/" 후에도 옛 session 잔존 (macOS Keychain)BITWARDENCLI_APPDATA_DIR=$HOME/.bw-axe-customer 로 fresh isolated dir
Caddyfile /vault no trailing slashvault access (step 17 health check)SPA HTML relative path 가 root 옆 resolve → asset 503/vault/vault/ permanent redirect (Caddy path-only destination trailing slash strip 함정)

Vault OIDC SSO 통합 — 기존 Vaultwarden 운영 중인 customer 용

귀사가 이미 soohunkang/vault repo (운영자 측 vault platform) 또는 자체 fork 의 Vaultwarden 인스턴스를 운영 중이고 그것을 그대로 유지하기로 결정한 경우 (= RE^2 의 Q3 (a) 채택), axec stack 의 별도 axe-vaultwarden 신설을 skip 하고 기존 vault 에 OIDC SSO 만 추가합니다. 본 절은 그 통합 절차.

책임 분담

작업누가
~/vault repo / compose.yaml / env_file 의 OIDC env 추가 + force-recreate귀사 IT (vault 운영 책임)
client_secret view-once URL 발사운영자 (axe secret send)
cloudflared ingress 의 /vault path 를 503 placeholder → vault-caddy 호스트 포트로 변경운영자 (axelabs.ai zone tunnel 운영 책임)
Vault Organization 생성 + 첫 admin invite귀사 admin (web UI)

절차 (양측 협업, ~30 분)

1. 운영자 — client_secret view-once URL 발사

axe secret send AZURE_{CUSTOMER_UP}_VAULTWARDEN_CLIENT_SECRET --service vault --customer {customer} --days 1 --access 1

귀사가 URL 받으면 1 회만 열어서 secret 값 캡처 후 즉시 안전 보관.

2. 귀사 IT — ~/vault/ 의 env_file (또는 compose.yaml environment: 영역) 에 다음 12 key 추가/변경

먼저 현 vault 의 secrets 보관 위치 확인:

cd ~/vault grep -E 'env_file|environment:' compose.yaml | head -5

env_file: ./vault.env (또는 비슷한 경로) 가 보이면 그 파일 편집. compose.yaml environment: 블록 inline 도 가능.

추가/변경할 12 key (기존 SIGNUPS_ALLOWED 가 false 면 true 로 변경):

# === DOMAIN — axec stack 가 사용할 외부 URL (cloudflared ingress) === DOMAIN: "https://{customer}.axelabs.ai/vault" # 기존 Tailscale FQDN 이면 변경 # === OIDC RP — Microsoft Entra ID === SSO_ENABLED: "true" SSO_ONLY: "false" SSO_AUTHORITY: "https://login.microsoftonline.com/{TENANT_ID}/v2.0" SSO_CLIENT_ID: "{vaultwarden_client_id}" SSO_CLIENT_SECRET: "{받은 secret 값}" SSO_SCOPES: "openid profile email offline_access" SSO_DEBUG_TOKENS: "false" # === 4-block: 첫 employee 가입 차단 회피 (D-ops-24/26/27) === SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION: "true" SSO_SIGNUPS_MATCH_EMAIL: "true" SIGNUPS_ALLOWED: "true" # 기존 false 면 변경 필수 ORGANIZATION_INVITE_AUTO_ACCEPT: "true"

placeholder 4:

  • {TENANT_ID} = axelabs-bootstrap-{customer}.jsontenant_id
  • {vaultwarden_client_id} = 동일 JSON 의 apps.vaultwarden.client_id
  • {받은 secret 값} = step 1 view-once URL
  • {customer} / {CUSTOMER_UP} = customer id / 대문자

3. 귀사 IT — force-recreate

cd ~/vault docker compose up -d --force-recreate vault-app # 또는 vaultwarden / 본인 컨테이너명

4. 운영자 — cloudflared ingress 의 /vault path 를 vault-caddy 로 라우팅

운영자가 customer macmini 의 ~/.cloudflared/config.yml/vault block 을 503 placeholder → vault-caddy 의 host port (트루비아 vault-caddy 는 보통 :8222, HTTPS 는 :8443) 로 변경 후 cloudflared 재시작. 본 step 은 customer 측 추가 작업 없음.

5. 검증 — SSO 직링크

https://{customer}.axelabs.ai/vault/#/sso

웹 UI 에 SSO Identifier 입력 화면이 나오면 OK. Identifier = 운영자 측이 customer 별 명명 (예: REALCHOICE 대문자 권장 — Bitwarden Send 본문에 명시).

첫 employee 시점 — Vault Organization + invite (D-ops-32)

귀사 admin 이 SSO 로 첫 로그인 후 web vault 의 Admin Console:

  1. Organization 생성 — 이름 = {CUSTOMER_UP} 대문자 (예: REALCHOICE)
  2. Collection 4 개 신설 (D-ops-32 v1):
    • Platform — Service Secrets (operator only)
    • Platform — Infrastructure (operator only)
    • {Customer Entity} (전직원 RW)
    • Shared Tools (전직원 RW)
  3. 직원 invite — 기존 운영자 측 invite-members.sh 패턴 또는 web UI 직접
  4. dual-identity 권장 (D-ops-29) — admin 직원 별도 ai@{customer-domain} (automation) + 실제 사람 계정 2 identity 둘 다 Owner

함정

함정결과회피
SSO_ONLY: "true" 설정Entra 장애 시 운영자 lockout (master password 진입 불가)false 유지 (D-ops-27)
SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION: "false" (Timshel default)첫 employee SSO “Your provider does not send email verification status” 차단true 명시 (D-ops-24)
SIGNUPS_ALLOWED: "false"첫 employee JIT signup “Failed to retrieve the invitation” 차단true (D-ops-26)
Vault UI 이메일-first 화면이 SSO Identifier 가림직원이 가입 절차 못 찾음/vault/#/sso 직링크 안내
client_secret 평문 메일 전송영구 보관 노출view-once URL (axe secret send)
Vaultwarden Timshel 1.34.1-6 + bw CLI 2026.xTypeError: toWrappedAccountCryptographicState crashbw CLI 2025.7.0 pin (npm install -g @bitwarden/[email protected])

상세 결정 근거: auth.mdx · D-ops-24 · D-ops-26 · D-ops-27 · D-ops-29 · D-ops-32.

정기 점검

주기작업
매일자동 backup + integrity check (운영자 측)
매주운영자 → 귀사 IT health report
매월secret 만료 30일 전 알림 (운영자 → 귀사)
분기Restore drill (운영자 측 자동)
연 1회보안 감사 협의

종료/이전 시

귀사가 AXE Labs 서비스 종료 결정 시:

  1. 데이터 export (frame DB dump + Vaultwarden export + Blueprint Workspaces)
  2. cold storage SSD 1개 사본 귀사에 인도
  3. macmini 의 AXE Labs 컨테이너 제거
  4. Microsoft Entra ID 의 3개 app 비활성화 (귀사 측)
  5. axelabs.ai zone 의 {customer} record 제거 (운영자 측)
  6. customers.yaml 의 entry 제거 (운영자 측)

데이터 보관 정책: export 후 자체 보관. AXE Labs 측 백업은 종료 +90일 후 폐기.

Last updated on