무색
기술블로그
에세이
연구
소개

무색

소프트웨어로 비즈니스의 가능성을 만듭니다. 웹·앱 개발, 음성 AI, 자동화 콘텐츠 제작까지 — 기술이 필요한 곳에 무색이 있습니다.

연락처

contact@museck.com

사업자 정보

상호: 무색

대표: 배성재

사업자등록번호: 577-58-00836

인천광역시 연수구 인천타워대로 323, 에이동 8층 801-802호 AB-132 (송도동, 송도 센트로드)

© 2026 무색. All rights reserved.
개인정보처리방침·이용약관·연락처
INCHEON, KR
Cloudflare Tunnel — 터널을 통한 내부 서비스 공개
홈랩 삽질기
2026. 1. 1.

Cloudflare Tunnel로 홈랩을 인터넷에 공개한 이야기

cloudflare-tunnelkuberneteshomelabkustomizetls

공인 IP 없이 서비스를 공개하고 싶다

홈랩에서 회사 홈페이지(museck.com)를 운영하고 있다. Next.js + PayloadCMS 기반이고 K8s 위에 올려두었는데, 문제는 이걸 외부에 공개하는 부분이었다. 가정용 인터넷이라 공인 IP가 수시로 바뀌고, 공유기에서 포트포워딩을 설정하는 것도 번거롭다. DDNS를 쓰면 되지 않냐고 할 수 있지만 ISP가 CGNAT를 걸어두는 경우도 있어서 근본적인 해결은 아니다.

스테이징 환경은 내부망(museck.xssh.org)에서 Traefik으로 접근하니까 상관없다. 프로덕션만 외부에 열면 된다.

Cloudflare Tunnel이라는 선택지

Cloudflare Tunnel(구 Argo Tunnel)은 내부 네트워크에서 Cloudflare Edge로 아웃바운드 연결을 맺는 방식이다. 핵심은 인바운드 포트를 하나도 열지 않는다는 점이다. K8s 안에서 cloudflared Pod가 Cloudflare 서버로 나가는 연결을 유지하고 있으면, 외부 트래픽이 그 터널을 타고 내부 서비스에 도달한다.

이 구조 덕분에 유동 IP, 포트포워딩, 방화벽 설정 같은 네트워크 문제를 전부 우회할 수 있다. 홈랩처럼 네트워크 환경을 마음대로 통제하기 어려운 상황에서 가장 현실적인 방법이라고 판단했다.

K8s에 cloudflared 올리기

구현 자체는 간단했다. Cloudflare 대시보드에서 Tunnel을 만들고 토큰을 받은 뒤, K8s에 cloudflared Deployment를 하나 추가하면 끝이다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cloudflared
  namespace: museck-prod
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: cloudflared
          image: cloudflare/cloudflared:latest
          args:
            - tunnel
            - run
            - --token
            - $(TUNNEL_TOKEN)
          env:
            - name: TUNNEL_TOKEN
              valueFrom:
                secretKeyRef:
                  name: cloudflared-tunnel
                  key: token

Cloudflare 대시보드에서 터널의 Public Hostname을 museck.com으로 설정하고, 백엔드 URL을 K8s 내부 서비스 주소(http://museck-app.museck-prod.svc.cluster.local:3000)로 지정하면 된다. 프로덕션 배포는 기존 스테이징과 동일하게 Kustomize overlay로 분리했고, ArgoCD Application도 별도로 등록해뒀다.

TLS 문제가 저절로 풀렸다

사실 처음에는 Cloudflare Tunnel 없이 해보려 했다. 프로덕션용 Kustomize overlay를 만들고 Traefik IngressRoute에 museck.com 도메인을 연결하려고 했는데, TLS 인증서에서 막혔다.

cert-manager의 Certificate 리소스는 같은 네임스페이스에만 Secret을 생성한다. traefik 네임스페이스에 있는 인증서를 museck-prod 네임스페이스에서 참조할 수가 없었다. 크로스 네임스페이스 참조를 위해 별도 솔루션을 도입하거나, 인증서를 복사하는 CronJob을 만들어야 하나 고민하던 차에 Cloudflare Tunnel로 방향을 틀었다.

결과적으로 TLS 종료를 Cloudflare Edge에 맡기게 되면서 K8s 내부에서는 인증서 자체가 불필요해졌다. cloudflared가 Cloudflare까지 암호화된 연결을 맺고, 내부 통신은 HTTP로 단순화했다. 인증서 관리 문제를 해결한 게 아니라 없앤 셈이다.

최종 아키텍처

정리하면 이런 구조가 됐다.

  1. 브라우저가 museck.com에 접속한다
  2. Cloudflare Edge에서 TLS를 종료하고 트래픽을 터널로 보낸다
  3. K8s의 cloudflared Pod가 트래픽을 수신해 museck-app 서비스로 프록시한다
  4. 내부 통신은 전부 HTTP라 인증서가 필요 없다

스테이징(museck.xssh.org)은 기존대로 Traefik IngressRoute를 유지한다. 내부 접근 전용이라 터널이 필요 없기 때문이다.

돌아보며

홈서버에서 서비스를 외부에 공개할 때 네트워크는 늘 걸림돌이다. 유동 IP에 DDNS를 붙이고, 공유기 포트포워딩을 뚫고, TLS 인증서까지 관리하다 보면 정작 서비스 개발에 쓸 시간이 줄어든다.

Cloudflare Tunnel은 이 복잡성을 통째로 Cloudflare에 위임한다. 내가 한 일이라곤 K8s에 Pod 하나 추가하고 토큰 넣어준 것뿐이다. 포트포워딩도 없고, 공인 IP도 몰라도 되고, 인증서도 신경 쓸 필요가 없어졌다.

홈랩이나 사이드 프로젝트를 외부에 열어야 할 때, 네트워크를 직접 제어하는 대신 제3자 서비스에 맡기는 것도 괜찮은 전략이다. 특히 Cloudflare Tunnel은 무료 플랜에서도 쓸 수 있으니 부담이 적다. 인프라보다 서비스에 집중하고 싶다면 한번 써보길 권한다.

자주 묻는 질문

홈랩에서 공인 IP 없이 웹 서비스를 외부에 공개할 수 있나요?
Cloudflare Tunnel을 사용하면 가능합니다. K8s 내부에서 Cloudflare Edge로 아웃바운드 연결을 맺기 때문에 인바운드 포트를 열지 않아도 외부에서 접속할 수 있습니다.
Cloudflare Tunnel을 쓰면 TLS 인증서를 따로 관리해야 하나요?
아닙니다. TLS 종료를 Cloudflare Edge에서 처리하기 때문에 K8s 내부에서는 인증서가 불필요합니다. 내부 통신은 HTTP로 단순화됩니다.
Cloudflare Tunnel은 무료로 사용할 수 있나요?
네, Cloudflare 무료 플랜에서도 Tunnel을 사용할 수 있습니다. K8s에 cloudflared Pod 하나만 배포하고 토큰을 설정하면 바로 동작합니다.
홈랩 삽질기(4/19)
Prev

containerd 기반 K8s에서 Docker 빌드하기: DinD 사이드카와 ArgoCD 크래시 수정기

Next

홈랩 모니터링, Prometheus 걷어내고 Loki로 갈아탄 이야기