Skip to Content

신규 Customer Onboarding

AI 요청 프롬프트

https://docs.axelabs.ai/ops/runbook/customer-onboarding 따라 신규 customer ([customer id]) D-day onboard 진행해줘. 진행: 1. D-day prerequisite 확인 — vault session unlock (bw + Keychain `axe.vault.session`, 8h cache) + customer IT 회신 `axelabs-bootstrap-{customer}.json` pack 수령 + customer macmini Tailscale ACTIVE direct 2. 페이지 Phase B 표 따라 5 step 중 현재 자동화 상태 분기 — `axe customers ingest` → `axe onboard --apply` → `axe deploy blueprint --apply` → `axe deploy hive --apply` (umbrella 미구현 시 순차) 3. 각 axe 명령은 dry-run (`--apply` 생략) 먼저 실행 + 변경 계획 사용자 확인 후 `--apply`. 매 step 결과 받고 다음. SSH 진입 / cloudflared ingress / vault collection 권한 점검 포함 4. 함정 발생 시 [/ops/known-gaps](/ops/known-gaps) 의 "D-day traps" 섹션 표 따라 우회 (Tailscale short alias / SSH non-login PATH / TXT+CNAME 공존 / keychain partition / bw cache stale / vault DOMAIN path / docker volume external 부재 / customers.yaml directory 잘못 생성 등 15+ 함정) 5. 5 step 완료 후 customer 측 health 검증 (frame/blueprint/hive 외부 endpoint 200) + Ship Log 한 줄 + customer IT 회신 ("배포 완료, 접속 안내")

본인 AI session = Claude Code / Cursor / ChatGPT 데스크탑 / Claude.app / 기타.

페이지 본문 = 사람이 직접 read 도 가능, AI 도 참고. AI 가 본 페이지 fetch 후 위 진행 순서대로 사용자와 step-by-step interactive 풀어나감.

신규 customer (예: realchoice) 의 macmini 에 AXE Labs 스택 전체를 배포하는 절차.

D-day TLDR — vault 먼저 풀어두면 1 명령

목표 (B-onboard-1shot): D-day 운영자 입력 = axe 명령 1 줄. vault 의 bw unlocksession prerequisite (8 시간 cache) — D-day touchpoint 아님.

Phase A — 세션 prerequisite (한 번, 이후 8 시간 자동)

작업명령
vault session unlock + Keychain cachebw unlock --raw | security add-generic-password -s axe.vault.session -a [email protected] -w "$(cat)" -U

이후 모든 axe secret/axe onboard/axe deploy 명령은 Keychain 의 BW_SESSION 자동 사용. 비번 재입력 없음.

Phase B — Deploy touchpoint (umbrella 후 1 명령, 현재 5 명령)

#운영자가 손대는 부분자동화backlog
0customer IT 에게 docs link 4 개 송부 (D-7)✅ 자력 — bootstrap.sh 가 docs.axelabs.ai 의 raw 로 노출 (2026-05-23 해소)B-onboard-bootstrap-publish
1customers.yaml{customer} 블록 + services 슬롯 작성axe customers add = stubB-onboard-customers-add
2customer IT pack.json → vault + customers.yaml 흡수axe customers ingest {id} {pack} (2026-05-23 구현) — dry-run/--apply + ruamel round-trip (comment 보존) + idempotentB-onboard-azure-pack
3axe onboard {customer} --apply (cloudflared + frame, 18-step)✅ 자동
4axe deploy blueprint {customer} --apply (Blueprint, 11-step)✅ 자동 (SSO 미설정 부팅)B-onboard-bp-sso
5Hive stack 수동 (ssh + docker compose)axe deploy hive 부재B-onboard-hive-deploy

→ 위 5 개를 묶는 umbrella 명령 B-onboard-umbrella 가 구현되면:

# 세션 prerequisite (8 시간 1 회) bw unlock --raw | security add-generic-password -s axe.vault.session -a [email protected] -w "$(cat)" -U # D-day — 줄 1 개 axe deploy customer {customer} --from-pack ~/Downloads/axelabs-bootstrap-{customer}.json --apply

운영자 D-day 입력 = 0 회 (vault 살아있으면) 또는 1 회 (vault 만료 시 unlock 한 번).

진정한 0 입력 D-day = (a) cron 이 bw unlock keep-alive 유지 + (b) umbrella 구현 + (c) pack.json 사전 수신. (c) 는 customer IT 측이 axelabs-bootstrap.sh 실행해서 안전채널로 보내주는 시점 의존 — 즉 운영자는 IT 회신만 기다리면 됨.

D-day 실제 명령 (2026-05-26 시점, B-customer-deploy-generalization Phase 1 ✅)

# 0. 운영자 vault unlock (master password 1 회) export BW_SESSION="$(bw unlock --raw)" security add-generic-password -s axe.vault.session -a [email protected] -w "$BW_SESSION" -U # 1. customer IT 회신 받은 axelabs-bootstrap-{customer}.json 흡수 (one-shot) # sso.tenant_id + sso.apps.{}.client_id fill + services manifest 슬롯 추가 # + vault push × 3 (3 client_secret) 묶음 axe customers ingest {customer} ~/Downloads/axelabs-bootstrap-{customer}.json --apply # (dry-run 으로 먼저 확인하려면 --apply 빼고 실행 → 변경 계획만 출력) # 2. Cloudflare tunnel + DNS + cloudflared launchd 부트스트랩 (1-9 step) axe onboard {customer} --apply --skip-frame # --skip-frame: frame stack 은 별도 `axe deploy frame` 로. 이전 18-step 묶음 패턴 폐기. # 3. customer 측 bw vault session bootstrap (interactive 1회 — customer IT 가 실행) # operator 가 SSH 으로 helper 를 push 한 후 customer IT 에게 실행 요청: scp /Users/axe/.axe/bw-bootstrap.sh {customer}-macmini:~/bw-bootstrap.sh ssh -t {customer}-macmini "brew install bitwarden-cli && \ ~/bw-bootstrap.sh https://<vault-url> <login-email>" # → ~/.bw-session (mode 600) 생성. wrapper 가 SSH non-interactive 호출 가능해짐. # 4. service 3종 customer-측 deploy (각각 13-step, ~5-15 분 each) axe deploy frame {customer} --apply axe deploy blueprint {customer} --apply axe deploy hive {customer} --apply

⚠️ {customer}services: 매니페스트를 선언한 신규 customer 자리 — sovereignty/self-deploy 로 졸업한 고객(realchoice/Truvia)은 대상 아님. 그 고객은 자기 macmini 에서 secret·compose·Caddy 를 자체 배포하고, customers.yamlservices: 매니페스트가 의도적으로 없어 axe deploy {svc} {customer}services … not declaredsys.exit 한다. 운영자 역할 = software supply (code/image) + 외부 노출 (DNS·cloudflared catch-all) 뿐. 근거: /ops/decisions (D-ops-40 / B-customer-sovereignty-architecture).

axe deploy {service} {customer} 가 동일한 13-step 흐름 수행: preflight → clone → vault_check → secrets_bootstrap (auto-gen if missing) → env_local → wrapper push → network → (blueprint 만) frame_mcp_token → compose up → (frame 만) proxy push → health → (frame+hive) register_entities → ingress swap.

axe onboard --skip-frame 권장 이유: 이전 18-step 통합 흐름은 frame stack 까지 묶였으나, 이제 customer-측 deploy 가 일반화되어 axe deploy frame {customer} 로 분리 호출이 idempotent + 재시도 안전. onboard 는 cloudflared layer 만 담당.

D-14 ~ D-7 (사전 협의)

작업책임
1. 가격·SLA 협의운영자
2. customer ID 정함 (x, newco 등)운영자
3. customer 측 IT 담당자 식별customer
4. macmini 구매 (M2/M3, 16GB+, 512GB+)customer
5. Tailscale 가입 + key 교환양측
6. customer 측 Microsoft 365 tenant 확인customer
7. customer 측 도메인 검증 준비 (TXT record 추가 권한)customer IT
8. axelabs.ai zone 의 {customer} A record 추가운영자 (Cloudflare)

D-7 (Azure 사전 등록 — customer IT 자력)

운영자가 customer IT 에게 보내는 것 = 링크 4 개 (별도 첨부 / 스크립트 메시지 X — 2026-05-23 B-onboard-bootstrap-publish 해소):

https://docs.axelabs.ai/partner ← 4 단계 흐름 (entry) https://docs.axelabs.ai/partner/macmini-prep ← macmini 사전 준비 (Tailscale, SSH, 절전) https://docs.axelabs.ai/partner/registration ← Option A CLI 1 줄 (axelabs-bootstrap.sh) https://docs.axelabs.ai/partner/handoff ← JSON pack 회신 양식

customer IT 가 30 분 (Option A) ~ 45 분 (Option B) 작업 → axelabs-bootstrap-{customer}.json 회신 (또는 텍스트 8 개 값).

JSON pack 스키마: axelabs-bootstrap/v1tenant_id + apps.blueprint/vaultwarden/frame_mcp 각각의 client_id + client_secret + (frame_mcp 만) application_id_uri + scope + redirect_uris. 운영자가 받으면 B-onboard-azure-packaxe customer ingest 가 1 줄로 흡수 (구현 후) — 현재는 수동 paste + axe secret push × 3.

운영자가 받으면:

  1. client_secret 3개 → vault 로 push (Keychain 직접 push 는 폐기 — 비밀의 SoT = Vaultwarden, D-ops-17):
    axe secret push AZURE_{CUSTOMER}_BLUEPRINT_CLIENT_SECRET --service blueprint --customer {customer} axe secret push AZURE_{CUSTOMER}_VAULTWARDEN_CLIENT_SECRET --service vaultwarden --customer {customer} axe secret push AZURE_{CUSTOMER}_FRAME_MCP_CLIENT_SECRET --service frame --customer {customer}
    (각 명령은 Value for ...: 프롬프트 → 안전채널로 받은 값 붙여넣기. 매니페스트에 customer service 슬롯이 사전 등재돼 있어야 함 — B-onboard-azure-pack.)
  2. customers.yaml 에 entry 추가:
    {customer}: legal_name: "<...>" primary_domain: "<...>" public_domain: "{customer}.axelabs.ai" entities: ["<...>"] tailscale_host: "{customer}-macmini" sso: provider: "microsoft_entra_id" tenant_id: "<...>" apps: blueprint: client_id: "<...>" client_secret_env: "AZURE_{CUSTOMER}_BLUEPRINT_CLIENT_SECRET" redirect_uri: "https://{customer}.axelabs.ai/api/auth/callback/azure-ad" vaultwarden: client_id: "<...>" client_secret_env: "AZURE_{CUSTOMER}_VAULTWARDEN_CLIENT_SECRET" redirect_uri: "https://{customer}.axelabs.ai/vault/identity/connect/oidc-signin" frame_mcp: client_id: "<...>" client_secret_env: "AZURE_{CUSTOMER}_FRAME_MCP_CLIENT_SECRET" application_id_uri: "https://{customer}.axelabs.ai/frame/mcp" redirect_uris: - "https://claude.ai/api/mcp/auth_callback" - "https://claude.com/api/mcp/auth_callback" scopes: - "openid" - "profile" - "email" - "https://{customer}.axelabs.ai/frame/mcp/mcp.access" user_entity_map: {} default_entities_by_domain: "&lt;primary_domain&gt;": ["&lt;entity&gt;"] onboarded: "&lt;date&gt;"
  3. cloudflared 중앙 tunnel ingress 편집불필요 (2026-05-23 drift 정정). axe onboardcustomer 별 독립 tunnel 을 customer macmini 에 생성/launchd 등록함 (_render_cloudflared_config in /Users/axe/.axe/bin/axe). 중앙 /Users/axe/.axe/tunnels/axelabs/config.yml 편집 의 D-7 의무는 사라짐. axe macmini 측 cloudflared 는 docs.axelabs.ai / admin.axelabs.ai 등 운영자 자기 서비스 전용.
  4. cloudflared 재시작 — 위와 동일. customer 측 tunnel 은 axe onboard step 8 의 launchd 가 자동 boot.
  5. Cloudflare zone 의 axelabs.ai 에서 {customer} A record 추가 — 불필요. axe onboard step 5 가 Cloudflare API 로 자동 CNAME 생성 (<tunnel-uuid>.cfargotunnel.com).

D-day (~1 시간, 자동)

운영자 머신에서 — 상단 D-day TLDR 참조. 핵심 흐름:

# Dry-run 으로 확인 (변경 0) axe onboard {customer} # 실제 적용 (cloudflared + frame) axe onboard {customer} --apply # Blueprint (별도 명령 — 통합은 B-onboard-1shot) axe deploy blueprint {customer} --apply

axe onboard 가 18-step 을 순차 실행 (Tailscale SSH 로 customer macmini 에 push):

Step작업 (실제 axe CLI 코드 기준)
1Tailscale up / customer macmini reachable 확인
2customer meta 검증 (customers.yaml entry, Tailscale FQDN)
3SSH probe (key 인증)
4cloudflared 터널 생성 (기존 있으면 reuse)
5Cloudflare DNS A record 생성
6cloudflared credentials.json push → macmini
7cloudflared config.yml push (ingress 규칙 포함)
8cloudflared launchd plist 등록 + boot
9cloudflared health check (curl /cdn-cgi/trace)
10frame git clone + Dockerfile preflight
11frame git submodule + asset 동기화
12macmini Keychain 에 secret push (vault, frame, blueprint, restic)
13macmini .env.local 생성 (env_file 용)
14docker compose up (postgres + frame-mcp-blue + frame-mcp-green + proxy)
15frame-mcp /health/ready poll (max 60s)
16frame register-entity × 각 entity + frame migrate
17axe-frame-proxy alias = blue 로 설정
18cloudflared ingress alias swap (axe-frame-proxy 가 frame upstream)

진행 중 어느 step 에서 실패하면 자동 rollback (기존 상태 유지). 운영자 화면에 명확한 오류 + 다음 단계 제시.

D+1 (검증 + Vault 부트스트랩)

운영자 ([email protected]) 측에서:

# 외부 health axe health {customer} # customer macmini ssh ssh {customer}-macmini "docker ps" # Blueprint admin 부여 ssh {customer}-macmini "docker exec blueprint-app pnpm prisma db execute --stdin" <<EOF UPDATE User SET role = 'admin' WHERE email = '&lt;ADMIN_EMAIL&gt;'; EOF # 첫 frame entity 등록 (chart auto-seed 적용, D-ops-21) ssh {customer}-macmini "docker exec frame-mcp-blue python -m frame.cli register-entity --id &lt;entity_id&gt; --legal-name '<법인명>' --kind corporate --accounting-standard ksme" # 첫 hive entity 등록 (frame mirror) ssh {customer}-macmini "docker exec hive-mcp-blue python -m hive.cli register-entity --id &lt;entity_id&gt; --legal-name '<법인명>'" # PII passphrase 2개 vault push + frame/hive deploy (axe customer 의 deploy-axep.sh 패턴) # 일반화된 deploy-new-entity.sh 가 자동 처리 (D-ops-31 후속 일반화): # bash /Users/axe/.axe/vault/deploy-new-entity.sh &lt;customer&gt; &lt;entity_id&gt; "&lt;법인명&gt;"

Vault 부트스트랩 — axe vault bootstrap {customer} (D-ops-33)

운영자 mac 에서 1 명령:

# Dry-run (default) — 현재 4 key 적용 상태 진단 axe vault bootstrap {customer} # 실 패치 + axe-vaultwarden force-recreate axe vault bootstrap {customer} --apply

명령 자동 흐름:

  1. SSH 로 customer macmini 의 /Users/{ssh_user}/.axe/vault/docker-compose.yml 읽음 (axe customer 는 local exec)
  2. 4 key (D-ops-24/26/27) 적용 상태 진단 — 이미 OK 면 skip
  3. 누락 key 만 patch (in-place, anchor = SSO_SIGNUPS_MATCH_EMAIL 다음 줄)
  4. docker compose up -d --force-recreate axe-vaultwarden
  5. Idempotent — 재실행 안전

적용되는 4 key:

SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION: "true" # D-ops-24 SIGNUPS_ALLOWED: "true" # D-ops-26 SSO_ONLY: "false" # D-ops-27 — emergency MP fallback 보존 ORGANIZATION_INVITE_AUTO_ACCEPT: "true" # D-ops-27 — 직원 Accept 자동

(INVITATIONS_ALLOWED=false 는 기존 docker-compose 의 default — JIT 통일.)

이 명령 빠지면 첫 employee 가 “Failed to retrieve the invitation” / “Your provider does not send email verification status” 등 차단 (D-ops-24, D-ops-26, D-ops-27 참조).

D+2 (직원 onboarding + Vault 첫 멤버 invite)

직원 SSO 안내

운영자 → customer admin 으로 신규 직원 온보딩 URL 전달.

customer admin 이 자기 직원들에게 안내. 각자 Frame connector 4-step setup 따라 설정.

Vault 접속 안내 (troubleshooting 의 Vault 섹션 참조):

  • 직링크: https://{customer}.axelabs.ai/vault/#/sso
  • Identifier: 그 customer 의 org 이름 (예: AXE, REALCHOICE)

Vault Organization + 직원 invite

customer admin (또는 운영자 SSH proxy) 가:

  1. Web vault → Admin Console → org 생성 ({CUSTOMER} 대문자 권장, 예: AXE / REALCHOICE)
  2. dual-identity 권장 패턴 (D-ops-29):
    • ai@{customer-domain} = 자동화 / bot identity (Graph token 발행, proactive DM, agent run)
    • 실제 admin 직원 별도 계정 = 사람 작업 identity
    • 둘 다 vault Owner + access_all=1
  3. 직원 invite — /Users/axe/.axe/vault/invite-members.sh 패턴 (customer 별 변수만 교체)
  4. Collection 구조 v1 (D-ops-32):
    • entity 1개 customer (예: realchoice): 4-collection 단순 구조
      • Platform — Service Secrets (operator only)
      • Platform — Infrastructure (operator only)
      • {Customer Entity} (전직원 RW)
      • Shared Tools (전직원 RW)
    • entity 다수 customer (예: axe 의 axec/axev/axep): 6-collection (entity별 분리)

D+7 (안정화 점검)

  • frame audit_log 활성? (실제 분개 1건 이상 발생?)
  • backup 정상? (restic -r /Users/axe/.axe/backups/local snapshots --password-file ...)
  • 직원 첫 시도 시 누락 없음?

함정

함정결과회피
customers.yaml entry 빠뜨림onboard 18-step 실패step 2 가 자동 검증
Cloudflare A record 없음(해소 — axe onboard step 5 가 자동 생성)
customer macmini sleep modeonboard SSH 실패D-7 까지 절전 안 함 설정
Tailscale key 교환 안 됨step 1 실패D-7 까지 양방향 ping 검증
customers.yaml services: 섹션에 customer 슬롯 없음axe secret push 가 매니페스트 lookup 실패 ({env_name} not in manifest)services.{svc}.{customer}.secrets[] 슬롯 사전 등재. 현재 axe 만 등재됨 — realchoice 는 신규 작업 (B-onboard-azure-pack)
Cloudflare API token vault 미등재axe onboard step 4 의 _cf_token() 실패첫 onboard 전 1 회 axe secret push 로 등재 (B-onboard-cf-token-doc)
Blueprint 가 SSO 미설정으로 부팅axe deploy blueprint 후 첫 로그인 실패현재 cmd_deploy_blueprint docstring 명시 한계. customer Keychain 에 Azure secret 별도 push 필요 (B-onboard-bp-sso)
Hive stack 자동 배포 명령 부재axe deploy hive 가 없어서 매번 ssh + docker compose 수동B-onboard-hive-deploy
Vault SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION 미설정첫 employee SSO “Your provider does not send email verification status” 차단D+1 의 Vault 부트스트랩 4-block (D-ops-24)
Vault SIGNUPS_ALLOWED=false + INVITATIONS_ALLOWED=false첫 employee JIT 가입 “Failed to retrieve the invitation” 차단D+1 의 4-block (D-ops-26)
Vault SSO_ONLY=true 설정Entra 장애 시 운영자 lockout (master password 진입 불가)SSO_ONLY: "false" 유지 (D-ops-27)
Vault UI 이메일-first 화면이 SSO Identifier 가림직원이 가입 절차 못 찾음/vault/#/sso 직링크 안내 (troubleshooting)
frame/hive entity 추가 시 PII passphrase 빠뜨림그 entity 의 PII 작업 시점에 RuntimeErrordeploy-new-entity.sh 가 PII passphrase 2개 vault push + ship 자동화 (D-ops-31)
customer Vaultwarden 의 bw CLI 자동화 시 BW_SESSION 직접 export 만 함axe secret push 실패 (keychain 만 읽음)security add-generic-password -s axe.vault.session -a ai@... -w "$BW_SESSION" -U 단계 통합 (D-ops-31 부수 발견)
Vaultwarden Timshel 1.34.1-6 + bw CLI 2026.xTypeError: ... toWrappedAccountCryptographicState crashbw CLI 2025.7.0 pin (npm install -g @bitwarden/[email protected]). 항구 해소: B-vault-upstream-migration — dani-garcia/vaultwarden:1.36.0 native SSO (D-ops-28)

다음 customer

Last updated on