Skip to content

English {#english}

Step-by-step check of token, account, Zone, R2, and DNS before using Pulumi for R2/DNS. Prerequisites: CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID in .env.local. Covers R2 bucket names, CORS (prego-static-assets), and DNS. Full details: see Korean section below.


한국어 {#korean}

Runbook: Cloudflare 접속·권한 단계별 점검

목적: Pulumi로 R2·DNS를 쓰기 전에, 토큰·계정·Zone·R2·DNS를 순서대로 확인하는 방법.

사전: .env.localCLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID(R2/계정 확인용) 설정.


0. R2 버킷·CORS 정리 (참고)

버킷 이름 (코드와 동일, prego- 통일)*

Cloudflare 버킷 이름Pulumi 리소스 이름용도
prego-static-assetsprego-static-assets정적 에셋(폰트 등). CORS 적용 대상.
prego-usage-rawprego-usage-rawUsage 원시 데이터. CORS 없음.
prego-logsprego-logsLogpush·관측성 로그. Ref: logpush-setup.md.
  • 409 방지: 코드에서 get_r2_bucket로 Cloudflare 존재 여부를 먼저 확인한다. 이미 있으면 버킷 생성은 하지 않고 CORS만 적용한다. state에 없어도 409 없이 pulumi up 한 번에 진행된다. (수동 import 없이 동작.)

CORS (prego-static-assets 전용) · 리소스: prego-static-assets-cors · Origins: https://app.pregoi.com, https://pregoi.com, https://x.pregoi.com, https://prego-web-anm.pages.dev, http://localhost:3000, http://127.0.0.1:3000 · Methods: GET, HEAD · Headers: * · Max age: 3600초

수동 import가 필요한 경우: state와 Cloudflare가 어긋나면 ./run-up.sh import 'cloudflare:index/r2Bucket:R2Bucket' prego-static-assets <ACCOUNT_ID>/prego-static-assets/default (및 prego-usage-raw) 후 ./run-up.sh up. Cloudflare R2 → prego-static-assets → Settings → CORS에서 값 확인.


0-2. Control Plane용 D1·KV (Pulumi 생성)

기획서(api-control-plane, tenant-onboarding-demo-www-plan)에 따라 prego-pulumi가 다음 리소스를 생성한다.

리소스Pulumi 이름용도
D1prego-d1Control Plane Worker 상태 DB (tenants_master, provision_jobs 등).
KVprego-tenant-origins (title)TENANT_ORIGINS 바인딩 — hostname → origin URL 라우팅.
R2§0 참고prego-static-assets, prego-usage-raw, prego-db-backups, prego-logs.

생성 절차

  1. pulumi config set cloudflare:accountId <ACCOUNT_ID> 또는 CLOUDFLARE_ACCOUNT_ID 환경 변수 설정.
  2. prego-pulumi에서 pulumi up 실행 → D1·KV·R2 생성(이미 있으면 스킵 또는 import).
  3. 스택 출력에서 d1_database_id, kv_namespace_id 확인:
    Terminal window
    pulumi stack output d1_database_id
    pulumi stack output kv_namespace_id
  4. prego-control-plane wrangler.toml에 반영:
    • [[d1_databases]]database_id = "<d1_database_id>", database_name = "prego-d1".
    • [[kv_namespaces]]binding = "TENANT_ORIGINS", id = "<kv_namespace_id>".
  5. Control Plane 마이그레이션 적용:
    Terminal window
    cd prego-control-plane
    wrangler d1 migrations apply prego-d1 --remote
  6. Worker 배포: wrangler deploy.

신규 환경: D1·KV를 Pulumi로 먼저 만든 뒤 위 4~6으로 바인딩·마이그레이션·배포하면 된다. Worker 코드는 prego-control-plane 레포에서 wrangler로 배포한다.


1단계 — 토큰 유효성

Terminal window
source .env.local
curl -s "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  • 기대: "success": true, "status": "active"
  • 실패: 401/403 → 토큰 재발급 또는 권한 확인

2단계 — Account ID 확인

  • Account ID는 32자리 16진수 (예: 3a555a2adb6585031cb8541ef5e6d2a0). Zone ID(영문+숫자 혼합)와 다름.
  • 목록 조회 (토큰에 계정 읽기 권한 필요):
Terminal window
curl -s "https://api.cloudflare.com/client/v4/accounts?per_page=1" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  • result[0].id 가 Account ID. .env.localCLOUDFLARE_ACCOUNT_ID와 일치하는지 확인.

3단계 — Zone(도메인) 접근

pregoi.com Zone ID 확인:

Terminal window
curl -s "https://api.cloudflare.com/client/v4/zones?name=pregoi.com" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  • 기대: result[0].id 에 Zone ID (예: 07904653049eb89fb9c4accb41009411)
  • 실패: result 빈 배열 → 해당 도메인 Zone이 없거나, 토큰에 Zone 읽기 권한 없음

4단계 — R2 버킷 목록

Terminal window
curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/r2/buckets" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  • 기대: "success": true, result 안에 버킷 목록 (또는 빈 배열)
  • 실패: 7003 “object identifier is invalid” → Account ID가 32자리 hex가 아님. 403 → R2 권한 없음.

4-2. R2 쓰기 권한 확인

목록(4단계)만으로는 읽기만 확인된 상태. 쓰기는 버킷 생성(POST)으로 확인.

1) 테스트 버킷 생성 (쓰기 권한)

Terminal window
source .env.local
# 이름은 고유하게 (이미 있으면 409)
TEST_BUCKET="prego-write-test-$(date +%s)"
curl -s -w "\nHTTP_CODE:%{http_code}" -X POST \
"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/r2/buckets" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"name\":\"${TEST_BUCKET}\"}"
  • 성공: 응답에 "success": true, HTTP 200. → 버킷 생성(쓰기) 권한 있음.
  • 실패: 403 → 토큰에 R2 쓰기 권한 없음. 대시보드에서 API 토큰에 R2 Object Read & Write 또는 R2 Edit 추가.

2) 테스트 버킷 삭제 (정리)

쓰기 확인 후 같은 토큰으로 삭제해 두면 정리됨.

Terminal window
curl -s -w "\nHTTP_CODE:%{http_code}" -X DELETE \
"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/r2/buckets/${TEST_BUCKET}" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  • 참고: 버킷 안의 객체(파일) 업로드(PUT) 는 R2 S3 호환 API + R2 전용 API 토큰/키를 쓰며, 위 Cloudflare API 토큰과는 별도. “버킷을 만들 수 있는가”만 확인하려면 1)으로 충분.

5단계 — DNS 레코드 목록 (node-01 존재 여부)

Zone ID를 위 3단계에서 확인한 값으로 넣음:

Terminal window
ZONE_ID="07904653049eb89fb9c4accb41009411" # 3단계 result[0].id
curl -s "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=node-01.pregoi.com" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  • 기대: resultnode-01 A 레코드가 있으면, 이미 존재 → Pulumi는 create 대신 import 해야 함.
  • result[0].id 가 해당 레코드의 Record ID (import 시 사용).

6단계 — “An identical record already exists” (81058) 해결

Cloudflare에 이미 node-01 A 레코드가 있어서 Pulumi가 create 시 81058을 내는 경우.

1) Record ID 확인 (5단계 curl 응답의 result[0].id)

2) Pulumi로 해당 레코드 import

zone_id/record_id
cd /Users/marco/prego-pulumi
source .env.local
pulumi import 'cloudflare:index/dnsRecord:DnsRecord' prego-node-01-dns <ZONE_ID>/<RECORD_ID>

예 (Zone ID·Record ID는 실제 값으로 교체):

Terminal window
pulumi import 'cloudflare:index/dnsRecord:DnsRecord' prego-node-01-dns 07904653049eb89fb9c4accb41009411/필요한레코드ID

3) 다시 up

Terminal window
./run-up.sh up
  • CORS 등 아직 안 만들어진 리소스만 생성되고, DNS는 state에 있으므로 변경 없음.

요약 체크리스트

순서확인 항목성공 시
0-2Control Plane D1/KVPulumi up → d1_database_id, kv_namespace_id 출력 → wrangler.toml 반영 → migrations apply → deploy
1토큰 verifysuccess true
2Account ID32자리 hex, .env와 일치
3Zone pregoi.comresult[0].id 존재
4R2 bucketssuccess true (목록 또는 빈 배열)
4-2R2 쓰기POST로 테스트 버킷 생성 → success true면 쓰기 권한 있음
5DNS node-01이미 있으면 record id 확보 → import
681058 시import 후 pulumi up

문서 위치: docs/runbook/cloudflare-step-by-step-check.md

Help