--- title: Cloudflare 도메인 활성화 런북 — quick tunnel → 고정 도메인 + Named Tunnel (+ Access) date: 2026-06-29 type: guide domain: homelab tags: [cloudflare, tunnel, dns, homelab] --- **Date:** 2026-06-29 **호스트:** ubuntu (home server) **도메인:** Networking / 운영 **용도:** 위키 포털의 임시 `*.trycloudflare.com` URL(리붓마다 변경)을 **고정 커스텀 도메인**으로 승격. --- ## 0. 왜 필요한가 (동기) 현재 포털은 Cloudflare **quick tunnel**로 노출 중이다. quick tunnel은 `kb-tunnel` 컨테이너가 재시작될 때마다 **URL이 바뀐다**(예: 직전 리붓 후 `https://space-recovery-personnel-experimental.trycloudflare.com`). 외울 수도, 북마크할 수도, 사내에 고정 공유할 수도 없다. → **본인 소유 도메인 + Named Tunnel**로 바꾸면 리붓해도 주소가 불변이고, 선택적으로 Cloudflare Access(SSO)로 private을 보호할 수 있다. > **현실 체크:** Named Tunnel은 **도메인이 Cloudflare 존(zone)으로 등록**돼 있어야 자동 CNAME을 만든다. DuckDNS 등 무료 서브도메인은 네임서버를 본인이 제어 못 하므로 **불가**. 즉 본인 소유 도메인(저렴해도)이 사실상 필수. ### 현재 상태 (런북 기준점) - Compose: `~/docs-publish/docker-compose.yml` — `kb-tunnel`(cloudflared)이 `command: tunnel --url http://localhost:8080` 으로 quick tunnel 실행. - Caddyfile: `~/docs-publish/Caddyfile` — `:8080` 단일 프런트도어. `/files*`→127.0.0.1:8081(dufs 다운로드), `/private*`→basic_auth, `/`+`/public*`→포털. - 좌측 nav(viz.js)는 `/public/_site.json`·`/private/_site.json`을 **절대경로(same-origin)** 로 fetch → 호스트를 쪼개면 base-URL 문제(5단계 참고). - cloudflared 아웃바운드: TCP/UDP **7844**(+443). 가정용 회선이면 보통 열림. --- ## 1. 도메인 구하기 | 옵션 | 내용 | 비고 | |---|---|---| | **(A) Cloudflare Registrar** ★추천 | 원가 판매. `.com` ≈ **$10.44/년**(등록=갱신 동일), 일부 TLD $4~5/년. WHOIS 프라이버시 무료 | 단, **이미 Cloudflare에 활성화된 존**에 대해서만 구매 메뉴가 열림 → 2단계(사이트 추가) 먼저. 네임서버가 자동 Cloudflare라 2단계가 자동 완료 | | (B) 외부 등록업체(Namecheap/Porkbun 등) | 첫 해 프로모가 쌀 수 있으나 갱신가가 비쌈. 네임서버를 직접 Cloudflare로 위임 | 2단계에서 네임서버 수동 변경 | | (C) 무료(Freenom .tk 등) | **2024년 폐쇄, 사용 불가**. DuckDNS/No-IP는 살아있으나 Named Tunnel/Access 불가 | 비추천 | **추천: (A) Cloudflare Registrar.** 도메인+DNS+터널+Access가 한 대시보드에서 끝나고 갱신가가 원가라 장기적으로 가장 단순/저렴. 짧은 이름이면 `.com`(~$10), 더 싸게는 `.net/.org/.dev`. > 이 문서는 도메인을 `example.com` 으로 표기. 실제 본인 도메인으로 치환. --- ## 2. 도메인을 Cloudflare에 추가·활성화 1. https://dash.cloudflare.com 로그인 (이메일 `yjs890403@gmail.com` 권장 — Access 정책 이메일과 일치시키면 편함). 2. **Add a domain**(또는 우상단 **+ Add → Existing domain**) → 도메인 입력 → **Continue**. 3. 플랜 **Free** 선택 → **Continue**. 4. DNS 스캔 결과 화면 → **Continue to activation**. 5. Cloudflare가 **네임서버 2개**(예: `mia.ns.cloudflare.com`, `todd.ns.cloudflare.com`) 제시. - **(A) Registrar 구매**: 이미 Cloudflare NS라 자동 통과. - **(B) 외부 등록업체**: 등록업체 대시보드 → 네임서버 설정 → 기존 NS 삭제 후 위 2개 정확히 입력 → 저장. **DNSSEC가 켜져 있으면 먼저 끄기**(켜진 채 NS 변경 시 도메인 먹통). **확인:** ```bash dig +short NS example.com # cloudflare.com 네임서버 2개가 떠야 함 ``` 활성화는 보통 수 분~수십 분(최대 24h). 완료 시 이메일 알림 + 대시보드 상태 **Active**(초록). --- ## 3. Named Tunnel 생성 (대시보드 토큰 방식 ★추천) + compose 배선 ### 3-A. 대시보드에서 터널 생성 1. 좌측 **Zero Trust** 진입(첫 진입 시 team name 1회 설정 + Free 플랜). 2. **Networks → Tunnels**(계정에 따라 **Networking → Tunnels**) → **Create a tunnel**. 3. 커넥터 **Cloudflared** → **Next**. 4. 터널 이름(예: `homelab`) → **Save tunnel**. 5. 환경에서 **Docker** 선택. 표시되는 설치 명령 안의 **토큰**(`eyJhIjoi....` 아주 긴 문자열)만 복사. (전체 docker run은 실행하지 말 것 — compose에 넣는다.) 6. **Next → Public Hostnames(또는 Routes) → Add a public hostname**: - **Subdomain**: 비우면 루트, 또는 `docs` - **Domain**: `example.com` - **Type**: `HTTP`, **URL**: `localhost:8080` ← 현재 Caddy 프런트도어 - **Save** - 가장 단순한 구성은 호스트네임 **1개**(`docs.example.com → localhost:8080`). 분리는 5단계. ### 3-B. compose 배선 (quick → named 교체) `~/docs-publish/.env` 에 추가: ``` CF_TUNNEL_TOKEN=eyJhIjoi....(복사한 토큰) ``` `~/docs-publish/docker-compose.yml` 의 `tunnel` 서비스 `command:` **한 줄만** 교체: ```yaml tunnel: image: cloudflare/cloudflared:latest container_name: kb-tunnel network_mode: host restart: unless-stopped command: tunnel --no-autoupdate run --token ${CF_TUNNEL_TOKEN} # quick tunnel 줄을 이걸로 교체 depends_on: [docs, fileshare] ``` (이전 `command: tunnel --url http://localhost:8080` 은 롤백용으로 주석 남겨도 됨.) 적용: ```bash docker compose -f ~/docs-publish/docker-compose.yml up -d tunnel docker logs --tail 30 kb-tunnel # 'Registered tunnel connection' 4개가량, 에러 없음 ``` 대시보드 Tunnels에서 상태 **HEALTHY** 확인. ### 3-C. (참고) CLI 방식 — 안 써도 됨 ```bash cloudflared tunnel login cloudflared tunnel create homelab # ~/.cloudflared/.json cloudflared tunnel route dns homelab docs.example.com ``` `~/.cloudflared/config.yml`: ```yaml tunnel: credentials-file: /home/jinsoo/.cloudflared/.json ingress: - hostname: docs.example.com service: http://localhost:8080 - service: http_status:404 ``` docker에선 `~/.cloudflared` 볼륨 마운트 + `command: tunnel run homelab`. ingress를 서버 파일로 관리하고 싶을 때만. **초보자는 3-A 권장.** --- ## 4. DNS 확인 3-A에서 Public Hostname 저장 시 Cloudflare가 **CNAME 자동 생성**(`docs → .cfargotunnel.com`, Proxied). ```bash dig +short docs.example.com # Proxied라 cfargotunnel이 아니라 Cloudflare 애니캐스트 IP(104.x/172.67.x)가 정상 ``` 브라우저 `https://docs.example.com` → 포털 표시. HTTPS 인증서는 Cloudflare 엣지가 자동 발급(Caddy `auto_https off` 유지 — TLS 종단은 엣지). --- ## 5. Caddy: 단일 :8080 유지(★추천) vs 호스트 분리(선택) ### 추천(가장 단순): `:8080` 유지 + 호스트네임 1개 **Caddyfile 수정 불필요.** 터널을 `localhost:8080`으로 보냈고 Caddy가 기존대로 `/files`·`/private`·`/` 라우팅. 단일 호스트라 viz.js의 절대경로 fetch 정상. - `https://docs.example.com/` → 포털 + public - `.../private/...` → basic_auth - `.../files/...` → 다운로드 허브 ### 선택 업그레이드: 호스트 분리(`docs.`/`kb.`/`files.`) 1. 3-A에서 Public Hostname 복수 추가(`docs→8080`, `files→8081` 등). dufs(8081)는 현재 `--path-prefix /files`라 서브도메인 루트로 쓰려면 prefix도 조정. 2. Caddyfile을 `:8080` 단일 → 호스트 기반 사이트 블록으로 재작성. > **⚠️ viz.js base-URL 함정:** 좌측 nav가 `/public/_site.json`·`/private/_site.json`을 절대경로로 fetch. public/private를 다른 호스트로 쪼개면 nav가 깨진다. → **public+private+포털은 같은 호스트(`docs.`)에 두고**, 다운로드(`files.`)만 분리가 안전. 완전 분리하려면 viz.js가 상대경로/호스트별 base-URL을 쓰도록 코드 수정 선행. **처음엔 단일 호스트로 가고 분리는 나중에.** --- ## 6. (선택·권장) Cloudflare Access로 private 보호 `/private`의 basic_auth를 엣지 SSO로 대체. 오리진(터널 뒤)이 더 안전해지고 이메일/Google 로그인으로 진입. 1. **Zero Trust → Access controls → Applications → Create new application → Self-hosted.** 2. **Add public hostname**: Subdomain `docs`, Domain `example.com`, **Path** `private` (→ `docs.example.com/private` 하위 전체 + `/private/_site.json` 보호). 3. **Add a policy**: name `allow-me`, Action **Allow**, Rule Selector **Emails** = `yjs890403@gmail.com` (회사 도메인 전체 허용 시 **Emails ending in** `@회사도메인` OR 규칙 추가). 기본 deny by default. 4. **Login methods**: 기본 **One-time PIN**(이메일 코드). Google 로그인은 Settings → Authentication에서 Google IdP 추가. 5. 동작 검증 후 **Caddyfile의 `/private` basic_auth 제거** 가능(엣지가 이미 막음). **검증 전에는 제거 금지.** ### ⚠️ 회사망/프록시 — 반드시 테스트 - `/files`(dufs)는 **의도적으로 GET-only·무인증** → 회사 프록시가 입력성 메서드를 막아도 다운로드(GET)는 통과(이 설계의 핵심). - 반면 **Access 로그인은 IdP 리다이렉트 + OTP 코드 제출(POST)** 포함. 회사 프록시가 POST/입력 제출을 막으면 **Access 로그인 자체가 실패**할 수 있음. - 권장 구성: - **`/files`(사내 다운로드 허브)에는 Access를 걸지 말 것** — 공개 GET 유지(회사망 호환). - **`/private`(주로 집 접근)에만 Access** — 집에서 OTP/SSO 로그인. - 사내에서 `/private`가 필요하면, 회사망에서 **Access 로그인(POST)이 실제로 되는지 먼저 테스트**하고 안 되면 basic_auth 유지. --- ## 7. 검증 체크리스트 & 롤백 ### 검증 ```bash docker logs --tail 20 kb-tunnel # connection registered, 에러 없음 dig +short docs.example.com # 104.x/172.67.x curl -sI http://localhost:8080/ | head -n1 # 200 (오리진 직통) curl -sI https://docs.example.com/ | head -n1 # 200 (공개) curl -sI https://docs.example.com/files/ | head -n1 # 200 (다운로드) # https://docs.example.com/private/... → Access 적용 시 로그인 화면(브라우저) ``` - 대시보드: Tunnels `homelab` = **HEALTHY**, 도메인 = **Active**. - 포털 좌측 nav 정상(단일 호스트면 문제없음). ### 롤백 (quick tunnel 즉시 복귀) 1. `~/docs-publish/docker-compose.yml`의 `tunnel.command`를 원복: `command: tunnel --url http://localhost:8080` 2. `docker compose -f ~/docs-publish/docker-compose.yml up -d tunnel` → `docker logs --tail 30 kb-tunnel | grep trycloudflare` 로 새 임시 URL 확인. - 도메인/DNS/터널은 남아있으니 문제 해결 후 3-B만 재적용하면 재전환. - Access만 문제면 Zero Trust → Access → Applications에서 앱 **Disable/Delete**(Caddyfile basic_auth 미삭제 전제)로 즉시 복귀. --- ## 빠른 의사결정 요약 - **도메인:** Cloudflare Registrar `.com`(~$10/년). 무료(DuckDNS)는 Named Tunnel 비호환. - **터널:** 대시보드 토큰 방식 → compose `command` 한 줄 교체. - **Caddy:** 단일 `:8080` + 호스트네임 1개(가장 단순, viz.js 무문제). 분리는 나중에. - **Access:** `/private`에만, `/files`는 공개 유지(회사망 다운로드 호환). 사내 Access 로그인 POST 가능 여부 별도 테스트. ## 검증 출처 (2026-06 확인) - Tunnel 원격 생성 + Docker 토큰 + Public Hostname: developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/get-started/create-remote-tunnel/ , /tunnel/setup/ - 도메인 추가/NS 변경/활성화: developers.cloudflare.com/fundamentals/manage-domains/add-site/ , /dns/zone-setups/full-setup/setup/ - Registrar 원가(.com ~$10.44): cloudflare.com/products/registrar/ , cfdomainpricing.com - Freenom 폐쇄(2024): netcraft.com/blog/cloudflare-loses-22-of-its-domains-in-freenom-tk-shutdown - Access self-hosted + 이메일 Allow: developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app/ , /policies/ > UI 라벨은 계정별로 **Networks/Networking → Tunnels**, **Public Hostnames/Routes** 로 다를 수 있음(기능 동일).