집 안에 둔 서버를 밖에서 접속하려고 하면 늘 한 지점에서 걸렸습니다. 공유기 포트포워딩은 설정 자체는 어렵지 않지만, 한 번 열어두면 계속 신경이 쓰입니다. DDNS도 공인 IP 여부나 ISP의 CGNAT 환경에 따라 생각보다 깔끔하게 끝나지 않을 때가 있었습니다.

포트포워딩을 열지 않기로 한 이유
이번 구성은 Rocky Linux 9 서버에서 Cloudflare Tunnel로 외부 접속을 붙이는 방식입니다. 서버가 Cloudflare 쪽으로 먼저 아웃바운드 연결을 만들고, 외부 요청은 그 터널을 통해 내부 서비스로 전달됩니다.
이 구조에서는 공유기에서 80, 443 같은 인바운드 포트를 열 필요가 없습니다. firewalld에도 웹 서비스 포트를 추가하지 않았습니다. SSH는 기존처럼 관리용으로만 제한해두는 쪽이 낫다고 봤고, 이 방향은 예전에 정리한 Rocky Linux 9 앵커글이나 SSH 하드닝글의 흐름과도 잘 맞았습니다.
Cloudflare 공식 문서에서도 Tunnel은 서버에서 실행되는 cloudflared가 Cloudflare와 연결을 맺는 방식으로 설명합니다. 설치와 로컬 관리형 터널 흐름은 공식 문서를 기준으로 확인했습니다.
- Cloudflare Tunnel 로컬 관리형 터널 문서: https://developers.cloudflare.com/tunnel/advanced/local-management/create-local-tunnel/
- cloudflared 다운로드 문서: https://developers.cloudflare.com/tunnel/downloads/
- Cloudflare 패키지 저장소: https://pkg.cloudflare.com/
비슷한 선택지를 나누면 아래처럼 정리됩니다.
| 방식 | 장점 | 주의할 점 |
|---|---|---|
| Cloudflare Tunnel | 포트포워딩 없이 HTTP 서비스를 외부에 공개하기 쉽고 Access 정책을 붙일 수 있음 | Cloudflare 프록시 제한을 받으며, 대용량 업로드에는 주의가 필요함 |
| 공유기 포트포워딩 + DDNS | 구조가 단순하고 직접 제어하기 쉬움 | 공인 IP, ISP CGNAT, 포트 노출 문제를 직접 관리해야 함 |
| VPN/WARP/Tailscale 계열 | 내부망처럼 접근할 수 있어 관리용으로 안정적 | 일반 웹 서비스처럼 도메인만 알려주는 공개 접근에는 별도 설계가 필요함 |
cloudflared 설치는 dnf repo 방식으로
Rocky Linux 9에서는 curl | bash 방식 대신 Cloudflare RPM 저장소를 추가한 뒤 dnf install로 설치했습니다. 홈서버처럼 오래 운영할 서버라면 패키지로 관리하는 편이 업데이트와 제거 면에서 깔끔합니다.

설치 후에는 SELinux 상태부터 확인했습니다. 저는 SELinux enforcing 유지를 전제로 작업했습니다.
firewalld도 확인했습니다. 이번 구성의 핵심은 외부에서 들어오는 HTTP/HTTPS 포트를 열지 않는 것이므로 http, https 서비스를 추가하지 않았습니다.
중요한 점은 터널용으로 firewalld 인바운드 포트를 열지 않았다는 것입니다. 서버가 밖으로 나가는 연결을 만들기 때문에 공유기 포트포워딩도 건드리지 않았습니다.
터널 생성과 config.yml 작성
Cloudflare 계정에 도메인이 연결되어 있다는 전제에서 진행했습니다. 먼저 브라우저 인증을 한 번 거칩니다.
제 환경에서는 아래처럼 인증 URL이 출력됐고, 브라우저에서 도메인을 선택한 뒤 인증 파일이 생성됐습니다.
이어서 터널을 만들었습니다. 이름은 나중에 알아보기 쉽도록 homelab-rocky9로 잡았습니다.
설정 파일은 /etc/cloudflared/config.yml에 두고 systemd에서 안정적으로 읽도록 했습니다. 아래 예시는 Immich를 http://localhost:2283으로 연결하는 형태입니다. 실제 도메인은 본인 도메인에 맞게 바꾸면 됩니다.
Cloudflare 문서에서는 마지막에 catch-all 규칙을 두는 흐름을 안내합니다. 그래서 맨 아래에 http_status:404를 넣어 정의하지 않은 호스트는 막히게 했습니다.
DNS 라우팅은 아래처럼 잡았습니다.

설정 검증도 한 번 해두는 편이 좋습니다.
systemd 등록과 재부팅 복구 확인
수동 실행으로만 두면 서버 재부팅 때 터널이 내려갈 수 있습니다. 그래서 바로 systemd 서비스로 등록했습니다.
정상이라면 대략 이런 로그가 보입니다.
재부팅 후 자동으로 복구되는지도 확인했습니다.
다시 접속한 뒤 아래 명령을 실행했습니다.
여기까지 확인해야 홈서버 운영용으로 믿고 쓸 수 있습니다. 단순히 접속이 되는지보다 서버 재부팅 후에도 터널이 자동으로 살아나는지가 더 중요했습니다.
Immich 백업에서 만난 100MB 제한
Cloudflare Tunnel을 붙인 뒤 가장 먼저 확인한 서비스는 Immich였습니다. 사진 백업은 잘 됐지만, 모바일에서 찍은 영상 하나가 계속 실패했습니다. 처음에는 Immich 설정이나 nginx 업로드 제한을 의심했는데, 로그를 보니 원인은 다른 쪽에 가까웠습니다.

Immich 모바일 백업 중 대용량 영상에서 남은 로그입니다.
Cloudflare의 Request body size limit 기준으로 Free와 Pro 플랜은 요청 본문 최대 100MB입니다. 이 제한을 넘는 업로드는 413 Request Entity Too Large로 막힐 수 있습니다.
- Cloudflare 요청 크기 제한 문서: https://developers.cloudflare.com/workers/platform/limits/
그래서 Immich를 Cloudflare Tunnel 하나로만 쓰는 건 제 기준에서는 애매했습니다. 사진 위주라면 문제가 적지만, 요즘 휴대폰 영상은 100MB를 넘는 경우가 흔합니다.
| 운영 방식 | 장점 | 주의할 점 |
|---|---|---|
| Immich 외부 접속을 Cloudflare Tunnel로만 사용 | 도메인 접속이 쉽고 포트포워딩이 필요 없음 | 100MB 초과 영상 업로드에서 413 오류가 날 수 있음 |
| 집 안에서는 LAN 주소로 직접 백업 | 대용량 영상 업로드가 안정적이고 빠름 | 외부에서는 별도 접속 경로가 필요함 |
| 외부 백업은 WARP 또는 VPN 경로로 분리 | 내부망 접근처럼 사용할 수 있어 대용량 업로드에 유리함 | 클라이언트 설정이 추가로 필요함 |
현재는 집 안에서는 Immich 앱이 로컬 주소를 보도록 두고, 밖에서는 조회나 가벼운 업로드만 Tunnel을 타게 나눴습니다. 외부에서 대용량 백업까지 해야 한다면 WARP나 VPN 계열을 함께 설계하는 쪽이 현실적입니다. 이 부분은 별도 Immich글에서 모바일 백업 기준으로 더 자세히 다룰 만했습니다.
Zero Trust Access로 관리 화면 보호하기
Tunnel을 열었다고 해서 모든 경로를 그대로 공개하고 싶지는 않았습니다. 특히 Immich admin, 서버 관리용 대시보드, 내부 도구처럼 자체 로그인이 있더라도 앞단에 한 겹 더 두는 편이 낫습니다.
Cloudflare Zero Trust의 Access 정책을 쓰면 특정 이메일이나 이메일 도메인 기준으로 인증 게이트를 붙일 수 있습니다. 공식 문서에서도 Access는 self-hosted application 앞에서 요청을 검사하고, 정책에 맞는 사용자만 통과시키는 방식으로 설명합니다.
- Cloudflare Access 애플리케이션 문서: https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/
- Cloudflare Access 정책 문서: https://developers.cloudflare.com/cloudflare-one/access-controls/policies/
예를 들어 admin.example.com은 Access Application으로 만들고, 정책에는 제 이메일만 허용했습니다.
| 보호 방식 | 장점 | 주의할 점 |
|---|---|---|
| Access 이메일 인증 | 관리 페이지 앞단에 인증 게이트를 둘 수 있음 | 이메일 OTP나 IdP 흐름이 한 번 추가됨 |
| 앱 자체 로그인만 사용 | 구성이 단순함 | 앱 취약점이나 로그인 페이지 노출을 그대로 감수해야 함 |
| IP 제한 | 특정 위치에서는 깔끔함 | 모바일망, 외부 작업 환경에서는 관리가 번거로움 |
설정 방향은 단순합니다. Zero Trust 대시보드에서 Access Application을 만들고, 도메인을 admin.example.com으로 지정한 뒤 Allow 정책에 사용할 이메일을 넣었습니다.
주의할 점은 OTP를 아무 이메일에나 열어두지 않는 것입니다. 홈서버 관리 화면은 특히 Everyone 허용으로 두지 않는 것이 중요합니다.

정리
Cloudflare Tunnel은 홈서버 외부 접속을 만들 때 꽤 실용적이었습니다. 특히 공유기 포트포워딩 없이 도메인 기반 HTTPS 접속을 붙일 수 있다는 점이 가장 컸습니다. Rocky Linux 9에서도 RPM 저장소를 추가해 dnf install cloudflared로 관리하면 설치 흐름이 깔끔했고, systemd 등록 후 재부팅 복구까지 확인하니 운영 부담도 적었습니다.
다만 Immich처럼 대용량 업로드가 많은 서비스는 100MB 제한을 먼저 생각해야 합니다. 저는 외부 조회와 가벼운 접근은 Tunnel, 집 안 백업은 LAN 직접 연결, 관리 화면은 Zero Trust Access로 보호하는 식으로 역할을 나눴습니다.
홈랩에서는 한 가지 도구로 전부 해결하려 하기보다 노출을 줄이고 필요한 경로만 열어두는 구성이 오래 운영하기에 편했습니다.




























