알파 서버 내부 앱을 deals.rinda.ai 로 안전하게 외부 공개하기 — 호스트 포트 0개, 오직 Cloudflare 터널로만.
deal-tracker-app 은 떠 있으나 짝이 되는 cloudflared 터널 컨테이너가 없고 .env 의 TUNNEL_TOKEN 이 비어 있는 것을 레퍼런스(rinda-html-share)와 대조해 확인.deal-tracker 생성(config_src=cloudflare) 후 연결 토큰 발급.deals.rinda.ai → http://deal-tracker-app:3001 설정 + DNS CNAME(proxied) 을 <tunnel-id>.cfargotunnel.com 으로 생성.~/deal-tracker/.env 에 주입하고 docker compose up -d cloudflared 로 기동 → 터널 healthy (4 conn).deals.rinda.ai 정상 접속·렌더 확인(거래 235건). 배포 완료.sbfm_definitely_automated: block 설정이 curl·스크립트 같은 자동화 요청을 엣지에서 403 처리한다(JA3/JA4 핑거프린트 기반이라 User-Agent 위장도 무효). 레퍼런스 html.rinda.ai 도 curl 로는 동일하게 403 → 브라우저로 검증하는 게 정답.
app 컨테이너가 이미 내부망에 떠 있다는 전제. 호스트 포트는 절대 열지 않는다.
# grinda 계정 ID 와 인증은 STEP 4(인증정보) 참고 curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCT/cfd_tunnel" \ -H "X-Auth-Email: $EMAIL" -H "X-Auth-Key: $KEY" \ -H "Content-Type: application/json" \ --data '{"name":"deal-tracker","config_src":"cloudflare"}' # → 응답의 result.id 가 TUNNEL_ID
curl "https://api.cloudflare.com/client/v4/accounts/$ACCT/cfd_tunnel/$TID/token" \
-H "X-Auth-Email: $EMAIL" -H "X-Auth-Key: $KEY"
# → result(문자열)가 cloudflared 가 쓸 TUNNEL_TOKEN
curl -X PUT ".../cfd_tunnel/$TID/configurations" \
-H "X-Auth-Email: $EMAIL" -H "X-Auth-Key: $KEY" \
--data '{"config":{"ingress":[
{"hostname":"deals.rinda.ai","service":"http://deal-tracker-app:3001"},
{"service":"http_status:404"}
]}}'
deal-tracker-net) 안에 있어 deal-tracker-app 이라는 컨테이너명으로 DNS 해석된다. 그래서 호스트 포트가 필요 없다.curl -X POST ".../zones/$ZONE/dns_records" \
-H "X-Auth-Email: $EMAIL" -H "X-Auth-Key: $KEY" \
--data '{"type":"CNAME","name":"deals",
"content":"<TUNNEL_ID>.cfargotunnel.com","proxied":true}'
# 알파 서버 ~/deal-tracker/.env TUNNEL_TOKEN=<발급받은 토큰> # 컨테이너 기동 (app 은 그대로, cloudflared 만 새로) cd ~/deal-tracker && docker compose up -d cloudflared
# 터널 상태: healthy / conns=4 확인 docker logs deal-tracker-cloudflared | grep "Registered tunnel" # curl 은 403 나도 정상(Bot Fight). 실제 브라우저로 접속 확인.
Claude Code 의 /cloudflare 스킬 — DNS·Workers·Pages·R2·터널 등 자연어로 관리.
| 항목 | 내용 |
|---|---|
| 호출 | /cloudflare 또는 “클라우드플레어로 …” 자연어 |
| 기본 계정 | personal (wks0968@gmail.com). grinda 소유 존(rinda.ai·grinda.ai·eodisalji.com) 작업일 때만 grinda 로 전환 |
| 주요 그룹 | Zone · Workers · KV · R2 · D1 · Analytics · 환경변수 · 버전 |
| DNS 수정 | MCP 미지원 → curl fallback (스킬 본문에 패턴 내장) |
| 공개 호스팅 | 단순 HTML 은 Pages(무료·무제한 대역폭) 추천 — 이 가이드도 그렇게 배포됨 |
# personal 자격증명 로드 CREDS=$(cat ~/.claude/credentials/cloudflare.json) export CLOUDFLARE_EMAIL=$(echo "$CREDS" | python3 -c "import sys,json;print(json.load(sys.stdin)['personal']['email'])") export CLOUDFLARE_API_KEY=$(echo "$CREDS" | python3 -c "import sys,json;print(json.load(sys.stdin)['personal']['global_api_key'])") export CLOUDFLARE_ACCOUNT_ID=$(echo "$CREDS" | python3 -c "import sys,json;print(json.load(sys.stdin)['personal']['account_id'])") wrangler pages project create <name> --production-branch=main wrangler pages deploy <dir> --project-name=<name> --branch=main --commit-dirty=true # → https://<name>.pages.dev/
스킬·스크립트가 읽는 자격증명 파일과, Cloudflare 쪽에서 키를 어떻게 얻는지.
경로: ~/.claude/credentials/cloudflare.json — 계정별 블록으로 분리.
{
"personal": {
"email": "wks0968@gmail.com",
"global_api_key": "<Global API Key>",
"account_id": "<Account ID>"
},
"grinda": {
"email": "admin@grinda.ai",
"global_api_key": "<Global API Key>"
}
}
| 단계 | 위치 |
|---|---|
| 1 | dash.cloudflare.com → 우상단 프로필 → My Profile |
| 2 | 좌측 API Tokens 탭 |
| 3 | 하단 API Keys → Global API Key → View (계정 비밀번호 재입력) |
| 4 | 키 복사 → 위 JSON 의 global_api_key 에 기입. 이메일은 로그인 이메일. |
대시보드에서 도메인 선택 → 우측 사이드바 API 섹션에 Account ID·Zone ID 표시. 또는 API 로:
curl "https://api.cloudflare.com/client/v4/zones/$ZONE" \ -H "X-Auth-Email: $EMAIL" -H "X-Auth-Key: $KEY" \ | python3 -c "import sys,json;print(json.load(sys.stdin)['result']['account']['id'])"
Zone:DNS:Edit, Account:Cloudflare Tunnel:Edit). 헤더는 X-Auth-Email/X-Auth-Key 대신 Authorization: Bearer <token>.| 리소스 | 값 |
|---|---|
| 앱 URL | https://deals.rinda.ai/ |
| rinda.ai Zone ID | 730c115be5ac17fb09629d6ec7c8b669 |
| 배포 디렉터리(알파) | ~/deal-tracker |
| 컨테이너 | deal-tracker-app (3001) + deal-tracker-cloudflared |
| 내부 네트워크 | deal-tracker-net (bridge) |
| 레퍼런스 패턴 | rinda-html-share → html.rinda.ai |