포트포워딩 없이 집 서버를 외부에 — Cloudflare Tunnel 자가호스팅
공유기 포트를 하나도 열지 않고 집 Mac mini 를 도메인으로 외부에 공개하는 Cloudflare Tunnel 설정 전체입니다. cloudflared 설치부터 config.yml ingress, 서비스 등록까지 여섯 단계와 석 달 운영에서 알게 된 것 넷을 적습니다.
집에 둔 미니PC로 서비스를 돌리면 마지막에 막히는 게 외부 노출입니다. 공유기 관리 페이지에 들어가 포트를 열고, IP가 바뀌면 또 손보고, 통신사가 막아둔 포트가 없길 기도하는 단계입니다. 이걸 안 거치고 도메인으로 바로 붙는 방법이 Cloudflare Tunnel입니다.
먼저 결론부터. cloudflared 데몬을 서버에 띄우면, 서버가 Cloudflare로 바깥을 향해 연결을 겁니다. 외부에서 서버로 들어오는 인바운드 포트를 하나도 열지 않습니다. 공유기 설정을 안 건드리고, 고정 IP도 필요 없고, 열어둔 포트가 없으니 공격면도 줄어듭니다. 셋업 흐름과 설정 파일을 정리합니다.
왜 포트포워딩이 아니라 아웃바운드인가
포트포워딩은 외부에서 집 공유기로 들어오는 길을 뚫는 방식입니다. 그러려면 공유기에 포트 매핑을 걸어야 하고, 외부에 노출되는 IP가 고정이어야 접속이 끊기지 않습니다. 가정용 회선은 IP가 유동인 경우가 많고, 통신사가 특정 포트를 막아두기도 합니다. 열어둔 포트는 그대로 외부에서 두드릴 수 있는 표면이 됩니다.
Tunnel은 방향이 반대입니다. 서버 안의 cloudflared가 Cloudflare 엣지로 나가는 연결을 상시 유지합니다. 외부 요청은 Cloudflare가 받아서, 이미 열려 있는 이 아웃바운드 연결을 타고 서버로 전달됩니다. 들어오는 포트를 열 필요가 없으니 공유기는 손대지 않아도 되고, IP가 바뀌어도 연결은 cloudflared가 알아서 다시 맺습니다.
셋업은 여섯 단계
도메인이 Cloudflare에 등록돼 있다는 전제로, 흐름은 다음과 같습니다.
- cloudflared 설치 — 서버 OS에 맞는 바이너리를 설치합니다.
- 로그인 —
cloudflared tunnel login. 브라우저로 인증하고 도메인(영역)을 고르면 인증서가 로컬에 저장됩니다. - 터널 생성 —
cloudflared tunnel create <이름>. 터널 UUID와 자격증명 JSON 파일이 생깁니다. - DNS 연결 — 도메인을 터널로 향하는 CNAME으로 라우팅합니다.
- config.yml 작성 — 어떤 호스트네임을 안쪽의 어떤 서비스로 보낼지(ingress) 정합니다.
- 실행 —
cloudflared tunnel run. 부팅마다 살아 있게 하려면 서비스로 등록합니다.
각 단계 명령을 이어 보면 이렇습니다.
# 2. 로그인 (브라우저 인증 후 cert.pem 저장)
cloudflared tunnel login
# 3. 터널 생성 → <UUID>.json 자격증명 파일 생성
cloudflared tunnel create calmdev
# 4. 도메인을 터널로 라우팅 (CNAME 자동 생성)
cloudflared tunnel route dns calmdev api.calmdev.kr
route dns는 Cloudflare DNS에 <UUID>.cfargotunnel.com을 가리키는 CNAME을 자동으로 만들어 줍니다. DNS 레코드를 손으로 만들 필요가 없습니다.
config.yml — 한 터널로 여러 서비스 라우팅
핵심은 ingress 규칙입니다. 호스트네임마다 내부 서비스(로컬 포트)를 매핑하고, 어디에도 안 걸리는 요청은 마지막 catch-all에서 404로 떨굽니다.
tunnel: <터널-UUID>
credentials-file: /Users/<계정>/.cloudflared/<UUID>.json
ingress:
- hostname: api.calmdev.kr
service: http://localhost:8080
- hostname: admin.calmdev.kr
service: http://localhost:3000
- service: http_status:404 # 매칭 안 되면 404 (필수, 맨 끝)
규칙은 위에서 아래로 순서대로 평가됩니다. 그래서 마지막 catch-all(http_status:404)은 반드시 있어야 하고 맨 끝에 둬야 합니다. 서비스를 추가할 땐 hostname 블록을 하나 더 넣고 그 도메인을 route dns로 연결하면 됩니다. 터널 하나로 여러 서비스를 내보낼 수 있어서, 부서별로 서버를 따로 노출할 때도 cloudflared 프로세스는 하나로 끝납니다.
서비스 주소는 cloudflared가 보는 기준입니다. 같은 호스트에서 돌면 localhost:포트, 컨테이너 네트워크 안이면 그 네트워크의 서비스 이름을 적습니다.
부팅 시 자동 실행 + 무료 범위
테스트는 cloudflared tunnel run calmdev로 충분하지만, 상시 운영하려면 서비스로 등록해 부팅마다 자동으로 뜨게 합니다.
cloudflared service install
비용 면에서, Cloudflare Tunnel 자체는 무료 플랜에서 쓸 수 있습니다. 개인 자가호스팅으로 도메인 몇 개를 내보내는 수준이면 추가 결제 없이 동작합니다. 한도나 정책 세부는 바뀔 수 있으니 운영 전 공식 문서를 한 번 확인하는 게 안전합니다. 접근 제어(Access)나 로드밸런싱 같은 상위 기능은 별도 플랜 영역이라, 단순 노출만 필요하면 무료 범위로 끝납니다.
석 달 넘게 써 본 결과
집에 둔 2018년형 Mac mini 에서 이 방식으로 API·관리자 화면·고객용 리포트 페이지를 내보내고 있습니다. 공유기 관리 페이지는 한 번도 열지 않았고, 집 IP 가 몇 번 바뀌었지만 DNS 를 고친 적이 없습니다. cloudflared 가 끊긴 연결을 스스로 다시 걸기 때문입니다.
운영하면서 알게 된 것을 넷만 적습니다.
한 포트에 여러 도메인을 태울 수 있습니다. ingress 는 호스트네임 기준이라, 실제로 고객 포털·리포트 열람·API 세 도메인이 같은 로컬 포트 하나로 들어가고 뒷단 앱이 Host 헤더로 갈라 처리합니다. 서비스가 늘어도 포트를 새로 열지 않습니다.
터널은 둘로 나눠 돌립니다. 회사 시스템용은 Docker 컨테이너(cloudflare/cloudflared 이미지)로, 다른 서비스용은 launchd 서비스로 따로 띄웁니다. 컨테이너로 돌리면 서버가 재시작될 때 다른 컨테이너와 같이 올라오고, 설정을 잘못 건드려도 다른 쪽 터널은 살아 있습니다.
config.yml 은 고치기 전에 백업합니다. 터널이 단일 진입점이라 이 파일 한 줄이 틀리면 그 터널의 서비스가 전부 같이 죽습니다. 날짜를 붙인 백업 파일을 옆에 두고 고친 뒤 재시작합니다.
무료 플랜의 범위는 HTTP(S) 트래픽입니다. SSH 같은 TCP 는 Cloudflare Access 나 cloudflared access 를 따로 설정해야 하고, Cloudflare 프록시를 거치는 요청은 본문 크기 상한(무료 플랜 100MB)이 있습니다. 큰 파일을 올리는 서비스에는 맞지 않습니다.
자주 묻는 질문
Q. Cloudflare Tunnel은 포트포워딩과 뭐가 다른가요? 포트포워딩은 외부에서 들어오는 인바운드 포트를 공유기에 여는 방식이라 고정 IP가 필요하고 통신사 포트 차단에 막힐 수 있습니다. Tunnel은 반대로 서버의 cloudflared가 Cloudflare로 나가는 아웃바운드 연결을 유지하고 외부 요청이 그 연결을 타고 들어와, 인바운드 포트를 하나도 열지 않습니다. 공유기 설정도 고정 IP도 필요 없습니다.
Q. 셋업은 몇 단계인가요? 여섯 단계입니다. cloudflared 설치 → 로그인 → 터널 생성 → DNS 연결 → config.yml ingress 작성 → 서비스 등록 순서이며, 도메인이 Cloudflare에 등록돼 있다는 전제입니다.
Q. 터널 하나로 여러 서비스를 노출할 수 있나요?
가능합니다. config.yml의 ingress 규칙에 호스트네임별로 내부 서비스(로컬 포트)를 매핑하고 맨 끝에 catch-all(http_status:404)을 둡니다. 서비스를 추가할 땐 hostname 블록을 더하고 route dns로 도메인을 연결하면 되며, cloudflared 프로세스는 하나로 끝납니다.
Q. 비용이 드나요? Cloudflare Tunnel 자체는 무료 플랜에서 쓸 수 있습니다. 개인 자가호스팅으로 도메인 몇 개를 노출하는 수준이면 추가 결제 없이 동작합니다. 접근 제어(Access)·로드밸런싱 같은 상위 기능은 별도 플랜 영역이고, 한도·정책은 바뀔 수 있으니 운영 전 공식 문서 확인을 권합니다.
정리
집 서버를 외부에 내보내는 가장 손쉬운 길은 포트를 여는 게 아니라, 서버가 바깥으로 연결을 거는 Cloudflare Tunnel 입니다. cloudflared 설치 → 로그인 → 터널 생성 → DNS 연결 → config.yml ingress → 서비스 등록, 여섯 단계면 공유기를 안 건드리고 도메인으로 붙습니다. 대신 터널이 단일 진입점이 되니 설정 파일은 백업하고 고치고, 무료 플랜의 범위(HTTP 트래픽 · 본문 100MB)는 미리 봐 둡니다.
만드는 과정은 calmdev.kr 에 계속 적습니다.
자주 묻는 질문
Cloudflare Tunnel 은 포트포워딩과 뭐가 다른가요?
포트포워딩은 외부에서 들어오는 포트를 공유기에 여는 방식이라 고정 IP 가 필요하고 통신사 포트 차단에 막힐 수 있습니다. Tunnel 은 서버의 cloudflared 가 Cloudflare 로 나가는 연결을 유지하고 외부 요청이 그 연결을 타고 들어와, 인바운드 포트를 하나도 열지 않습니다.
터널 하나로 여러 서비스를 노출할 수 있나요?
가능합니다. config.yml 의 ingress 에 호스트네임별로 로컬 포트를 매핑하고 맨 끝에 http_status:404 를 둡니다. 호스트네임 기준이라 여러 도메인을 같은 포트 하나로 보낼 수도 있습니다.
비용이 드나요?
Cloudflare Tunnel 자체는 무료 플랜에서 쓸 수 있습니다. 다만 무료 범위는 HTTP(S) 트래픽 위주이고 프록시를 거치는 요청은 본문 100MB 상한이 있어, SSH 같은 TCP 나 큰 파일 업로드에는 별도 설정이나 다른 방식이 필요합니다.