Cloudflare 도메인 활성화 런북 — quick tunnel → 고정 도메인 + Named Tunnel (+ Access)
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에 추가·활성화
- https://dash.cloudflare.com 로그인 (이메일
[email protected]권장 — Access 정책 이메일과 일치시키면 편함). - Add a domain(또는 우상단 + Add → Existing domain) → 도메인 입력 → Continue.
- 플랜 Free 선택 → Continue.
- DNS 스캔 결과 화면 → Continue to activation.
- Cloudflare가 네임서버 2개(예:
mia.ns.cloudflare.com,todd.ns.cloudflare.com) 제시.- (A) Registrar 구매: 이미 Cloudflare NS라 자동 통과.
- (B) 외부 등록업체: 등록업체 대시보드 → 네임서버 설정 → 기존 NS 삭제 후 위 2개 정확히 입력 → 저장. DNSSEC가 켜져 있으면 먼저 끄기(켜진 채 NS 변경 시 도메인 먹통).
확인:
dig +short NS example.com # cloudflare.com 네임서버 2개가 떠야 함
활성화는 보통 수 분~수십 분(최대 24h). 완료 시 이메일 알림 + 대시보드 상태 Active(초록).
3. Named Tunnel 생성 (대시보드 토큰 방식 ★추천) + compose 배선
3-A. 대시보드에서 터널 생성
- 좌측 Zero Trust 진입(첫 진입 시 team name 1회 설정 + Free 플랜).
- Networks → Tunnels(계정에 따라 Networking → Tunnels) → Create a tunnel.
- 커넥터 Cloudflared → Next.
- 터널 이름(예:
homelab) → Save tunnel. - 환경에서 Docker 선택. 표시되는 설치 명령 안의 토큰(
eyJhIjoi....아주 긴 문자열)만 복사. (전체 docker run은 실행하지 말 것 — compose에 넣는다.) - 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단계.
- Subdomain: 비우면 루트, 또는
3-B. compose 배선 (quick → named 교체)
~/docs-publish/.env 에 추가:
CF_TUNNEL_TOKEN=eyJhIjoi....(복사한 토큰)
~/docs-publish/docker-compose.yml 의 tunnel 서비스 command: 한 줄만 교체:
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 은 롤백용으로 주석 남겨도 됨.)
적용:
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 방식 — 안 써도 됨
cloudflared tunnel login
cloudflared tunnel create homelab # ~/.cloudflared/<UUID>.json
cloudflared tunnel route dns homelab docs.example.com
~/.cloudflared/config.yml:
tunnel: <UUID>
credentials-file: /home/jinsoo/.cloudflared/<UUID>.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 → <UUID>.cfargotunnel.com, Proxied).
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.)
- 3-A에서 Public Hostname 복수 추가(
docs→8080,files→8081등). dufs(8081)는 현재--path-prefix /files라 서브도메인 루트로 쓰려면 prefix도 조정. - 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 로그인으로 진입.
- Zero Trust → Access controls → Applications → Create new application → Self-hosted.
- Add public hostname: Subdomain
docs, Domainexample.com, Pathprivate(→docs.example.com/private하위 전체 +/private/_site.json보호). - Add a policy: name
allow-me, Action Allow, Rule Selector Emails =[email protected](회사 도메인 전체 허용 시 Emails ending in@회사도메인OR 규칙 추가). 기본 deny by default. - Login methods: 기본 One-time PIN(이메일 코드). Google 로그인은 Settings → Authentication에서 Google IdP 추가.
- 동작 검증 후 Caddyfile의
/privatebasic_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. 검증 체크리스트 & 롤백
검증
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 즉시 복귀)
~/docs-publish/docker-compose.yml의tunnel.command를 원복:command: tunnel --url http://localhost:8080docker 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 로 다를 수 있음(기능 동일).