보이지 않는 다리 — Cloudflare Tunnel로 우리집 블로그 외부 노출하기
셀프호스팅 구축기 9편. 도메인 산 다음, 우리집 컴퓨터까지 트래픽을 어떻게 끌어오나.
← 이전 편: 8편 — 24시간 안에 봇이 온다 (보안 P0)
→ 다음 편: 10편 — 블로그에 뭘 쓰면 안 되나 (개인정보 검열)
TL;DR (한 화면 요약)
- 문제: 우리집 미니PC에 WordPress를 띄웠는데, 산 도메인(
sticknstone.org)을 외부에서 어떻게 연결하나 - 옛 방식: 공유기 포트 열기 → 공인 IP DNS 등록 → SSL 갱신. 5가지 골치
- 새 방식: Cloudflare Tunnel — 미니PC가 Cloudflare에 outbound로 다리를 미리 놓는다. 공유기 구멍 X, IP 노출 X
- 도구:
cloudflared데몬을 Docker로 가동. 5분 - 공짜 보너스: WAF·DDoS·CDN·SSL·트래픽 통계 전부 무료
- 비용: 0원 (도메인 갱신비 연 $10 별도)
1. 풀고 싶은 문제
블로그(WordPress)는 우리집 미니PC에 띄워뒀다. 도메인(sticknstone.org)도 샀다. 그런데 이 둘이 어떻게 만나야 하나?
평범한 길 (포트포워딩) 5가지 골치
| 골치 | 왜 |
|---|---|
| 공유기 구멍 | 443번 포트 외부에 열면 평생 봇 공격 |
| 공유 IP | 통신사가 매번 바꿈. 자동 갱신 스크립트 필요 |
| 우리집 위치 노출 | IP만 알면 대략적 동네 추정 가능 |
| SSL 갱신 | 매 90일마다 Let’s Encrypt 직접 |
| 트래픽 폭주 | DDoS 맞으면 우리집 인터넷 마비 |
2. 다른 길: 다리를 놓는다
발상의 전환: 외부에서 우리집으로 들어오는 연결을 받지 말자. 대신 우리집에서 외부 어딘가로 나가는 연결을 미리 만들어두자.
flowchart LR
subgraph oldway["옛 방식 — 포트포워딩"]
A1[방문자] --> A2[공유기 포트 443 오픈]
A2 --> A3[미니PC 공개 IP]
A3 --> A4[WordPress]
A5[해커] -.공격.-> A2
end
subgraph newway["새 방식 — Cloudflare Tunnel"]
B1[방문자] --> B2[Cloudflare 서울 DC]
B2 -. 미리 열린 outbound 채널 .-> B3[미니PC cloudflared]
B3 --> B4[WordPress]
B5[해커] -.차단.-> B2
end
style A5 fill:#fdd,stroke:#a00
style B5 fill:#dfd,stroke:#0a0
style A3 fill:#fdd
style B3 fill:#dfd
핵심: 미니PC가 먼저 손을 뻗는다. 외부 → 우리집 흐름이 아니라, 우리집 → Cloudflare로 outbound 연결을 늘 열어둔다. 방문자 요청은 Cloudflare가 이 채널로 미니PC에 던진다.
호텔 비유
호텔 손님(미니PC)이 친구를 만나고 싶을 때.
- 평범한 길: 호텔 입구에 자기 방 번호를 크게 써붙임. 친구는 그 번호로 들어옴. 동시에 도둑도 옴.
- 다리의 길: 호텔 프론트데스크(Cloudflare)에 미리 메모를 남긴다. 내 친구 찾는 사람 있으면 객실로 연결해달라고. 친구는 이름만 대고, 프론트데스크가 안내한다. 방 번호는 외부 노출 X. 의심스러운 사람은 1차로 거른다.
3. 트래픽 흐름 — 방문자가 도메인 칠 때
sequenceDiagram
participant V as 방문자 브라우저
participant CF as Cloudflare 서울 DC
participant CD as cloudflared (미니PC)
participant WP as WordPress 컨테이너
V->>CF: GET https://sticknstone.org
Note over CF: WAF·DDoS 1차 필터
CF->>CD: 미리 열린 outbound 채널로 forward
CD->>WP: http://localhost:8090
WP-->>CD: HTML 응답
CD-->>CF: outbound 채널 회신
CF-->>V: SSL 종단·CDN 캐시 + 응답
4단계: 방문자 → Cloudflare(필터) → 다리 → 미니PC → 역순. 미니PC IP는 어디에도 안 등장.
4. 다리지기: cloudflared
이 outbound 채널을 우리집에서 유지하는 작은 데몬이 cloudflared — Cloudflare 공식 오픈소스.
왜 Docker로 띄우나
미니PC에 이미 Docker가 돌고 있다. 다른 컨테이너들과 같은 호텔에 묵는 게 자연스럽다.
flowchart TB
subgraph minipc["미니PC (Ubuntu 24.04)"]
subgraph docker["Docker 호스트"]
CD[cloudflared / network_mode host]
WP[wordpress-wordpress-1 :8090]
DB[(wordpress-db-1 MariaDB)]
RD[(wordpress-redis-1 Object Cache)]
UM[umami_umami-1 :3001]
UDB[(umami_db-1 Postgres)]
end
WP --> DB
WP --> RD
UM --> UDB
end
CF[Cloudflare 네트워크] -. outbound .-> CD
CD --> WP
CD --> UM
style CD fill:#ffe4b5,stroke:#d97706
style CF fill:#dbeafe,stroke:#1d4ed8
cloudflared만 network_mode: host로 띄워서 호스트의 localhost:8090(WP)와 localhost:3001(Umami)에 접근하게 한다.
설치 5분 가이드
폴더 + 설정 파일:
/home/user/cloudflared/
├── .env # TUNNEL_TOKEN=eyJh... (Cloudflare 대시보드에서 받은 토큰)
└── docker-compose.yml
docker-compose.yml:
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
network_mode: host
command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}
env_file: .env
가동 + 로그 검증:
cd /home/user/cloudflared
sudo docker compose up -d
sudo docker logs cloudflared --tail 20
성공 로그에 다음 4줄이 보인다 (Cloudflare 서울 데이터센터 4곳 동시 연결):
Registered tunnel connection ... location=icn06 protocol=quic
Registered tunnel connection ... location=icn01 protocol=quic
Registered tunnel connection ... location=icn05 protocol=quic
Registered tunnel connection ... location=icn06 protocol=quic
미니PC는 4중 백업 채널로 Cloudflare에 연결된다. 한 채널이 죽어도 나머지 3개가 살아있다.
5. 토큰은 위험하다 — 어디 두나
cloudflared가 Cloudflare에 자기를 증명할 때 쓰는 토큰. 발급 시 한 번 보여주고 끝.
토큰 다루기 원칙
.env파일에 평문 저장. 권한chmod 600(소유자만 읽기·쓰기)- 채팅·노트·git 커밋에 절대 평문 X
- 토큰 노출 의심 시 즉시 Cloudflare 대시보드에서 revoke + 재발급
정확한 명령
sudo chown user:user /home/user/cloudflared/.env
sudo chmod 600 /home/user/cloudflared/.env
6. 공짜로 따라오는 것
Cloudflare 무료 플랜으로 이 다리만 놓아도 따라오는 보너스:
| 보너스 | 설명 | 평소 가격대 |
|---|---|---|
| WAF (웹 방화벽) | SQL injection·XSS 알려진 공격 자동 차단 | 월 $20~ |
| DDoS 보호 | 트래픽 폭주 자동 흡수, 무제한 | 월 $200~ |
| CDN | 정적 파일 전 세계 캐싱. 외국 방문자도 빠르게 | 월 $10~ |
| SSL 자동 | Let’s Encrypt 갱신 신경 0 | 월 $5~ |
| 트래픽 통계 | Cloudflare 대시보드에서 그래프로 | (분석 도구) |
총합 비용: 0원. 도메인 갱신비 연 $10만.
7. 함정 — 우리가 실제로 만난 것
함정 1. Operating System 선택 헷갈림
Cloudflare 대시보드의 cloudflared 설치 명령 화면에서 OS를 골라야 한다. 처음에는 자기 윈도우 PC가 OS인 줄 알고 Windows를 골랐다. 틀렸다. cloudflared가 설치되는 곳은 미니PC(Ubuntu)지 내 윈도우가 아니다. Docker를 골랐어야 한다.
함정 2. 토큰을 LLM 채팅에 그대로 붙여넣음
복사한 토큰을 LLM 채팅에 보내면 그 채팅 내용은 외부 서버에 저장된다. 토큰은 카드 비밀번호급 민감 정보. 작업 끝나면 즉시 Cloudflare 대시보드에서 토큰 회수 권장.
함정 3. cloudflared가 어떻게 다른 서비스에 forward하나
cloudflared 컨테이너만 띄우면 Cloudflare와 연결은 되지만, 들어온 요청을 어디로 보낼지는 별도 설정이다. Public Hostname 설정이라고 한다. 다음 편(10편)에서 다룬다.
8. 검증
가동 직후 Cloudflare 대시보드의 Tunnel 페이지 하단 Connection Status를 본다.
Before: No connection detected yet
After: Connected (체크)
이 한 줄이 바뀌면 다리가 놓인 것이다.
FAQ
Q. Tailscale Funnel과 무엇이 다른가?
둘 다 NAT 우회 + 미니PC IP 비공개라는 점은 같다. Cloudflare Tunnel은 WAF·DDoS·CDN·자기 도메인 사용까지 무료로 묶어준다. Tailscale Funnel은 전용 도메인 강제 + 보호막 없음. 블로그용은 Cloudflare가 우위.
Q. 미니PC가 꺼지면 어떻게 되나?
다리가 끊긴다. 방문자는 Cloudflare에서 521(Web server is down) 에러를 본다. 미니PC가 다시 켜지면 cloudflared가 자동으로 다리를 재연결한다 (Docker restart: unless-stopped).
Q. Cloudflare가 트래픽을 보나? 개인정보 우려?
Cloudflare는 SSL을 자기가 종단한다 = 평문 트래픽을 본다. 신뢰 모델은 Cloudflare는 내 편이라는 가정. 신뢰 못 하면 적합 X (대안: 자체 reverse proxy + Let’s Encrypt + dynamic DNS).
Q. 무료 플랜 한계는?
대역폭 무제한, 사이트 수 무제한, Tunnel 수 무제한. 단 Cloudflare Workers·R2 같은 부가 서비스에 별도 한도. 블로그 1개 운영엔 무료 플랜이 평생 충분.
Q. 도메인이 .org가 아니어도 되나?
무관. .com / .net / .io / .dev 모두 동일하게 작동. 단 도메인이 Cloudflare DNS를 쓰는 게 가장 쉬움 (자동 DNS 등록).
다음 편 예고
10편에서는 Public Hostname을 설정해 sticknstone.org → WordPress로 매핑하고, 글에 무엇을 쓰면 안 되는지(개인정보 검열)를 다룬다.
한 줄 정리
집에 있는 컴퓨터에 블로그를 띄우려면 공유기에 구멍 뚫고 IP 노출하는 옛 방식 대신, 컴퓨터에서 Cloudflare로 outbound 채널을 미리 열어두는 Cloudflare Tunnel 방식이 깔끔하다. 그 채널을 유지하는 작은 데몬이 cloudflared. Docker로 띄우면 5분.

답글 남기기