내가 만든 서비스를 세상에 공유하는건 참 가슴 뛰는 일이다. 내 서비스를 얼마나 사람들이 써줄지 기대가 되는 순간이면서도, 동시에 나를 공격하는 공격자들에게 나를 노출시키는 일이기 때문이다.
일반적으로 백엔드를 사용하기 위해 선택하는 방법은, 홈서버의 경우 공유기에서 제공하는 DDNS를 이용하거나 내 공인IP의 포트를 외부에 노출한다. 나 역시 이 방법들을 시도했으나, 내 포트를 외부에 노출하는 순간부터 너무나도 무방비하게 나를 노출시키는 느낌이 들었고 다른 대안들을 찾아보다가 알아낸 것이 cloudflared 였다. 이걸 이용하면 DDNS 나 포트포워딩, 공유기 없이 홈서버를 웹에 제공할 수 있다.
Cloudflared 서비스 설명
cloudflared 는 cloudflare 와 내 홈서버 사이에 안전한 Tunnel을 만들어주는 VPN Client 다.
홈서버에 cloudflared를 켜면 cloudflared가 cloudflare 서버와 연결해서 터널을 만든다. 따라서 VPN Client 역할로서의 홈서버에서 먼저 cloudflare 서버에 연결해 연결성이 생기는 것이다.
외부 서비스에서 접속 요청이 오면 이 터널을 통해 연결되게 된다.
아래 그림을 보면 직관적으로 이해할 수 있을 것이다. 더 자세한 내용을 알고 싶은 분들을 위해 아래 링크를 남겨둔다.


DDNS 나 공유기를 활용한 것 대비 이점
구조가 이렇다 보니, 다른 방법으로 웹서비스를 제공하는 것보다 아래와 같은 장점이 있다.
- 외부 환경의 변화에서 상당히 자유로워진다
DDNS 설정을 바꾸거나 저장할 필요가 없다. 즉 통신사를 변경하거나 이사를 하거나 컴퓨터를 바꾸거나 공유기를 바꾸는 경우에도, 웹서비스를 외부에 제공하기 위한 별도의 인프라 조치가 필요없다. 그저 cloudflared 를 켜기만 하면 그 즉시 웹서비스가 제공된다. - 생성이 편하다
새로운 웹서비스를 오픈할 때, 별도의 설정을 할 필요없이 소스코드 docker-compose.yml 에 넣으면 된다. 그래서 한 서비스를 새로 오픈하고자 할 때, 이 작업에 약 5분정도면 충분하다. (물론 자주 오픈해서 경험이 있는에 대해서 말하는 것이다. 새로 학습하는데 걸리는 시간은 그보다는 길다)
cloudflared 를 홈서버에 띄우는 2가지 방법
위 서비스를 써서 서비스를 제공할 수 있는 방법은 크게 2가지로 나뉜다
- 홈서버 OS에 cloudflared 서비스를 daemon으로 켜기
- container로 cloudflared 서비스를 실행 (👍추천)
나는 학습시엔 1번을 했고, 실 운영에서는 2번 형태로 구성하고 있다. 나의 경우 하나의 홈서버에서 여러 서로 다른 서비스를 제공하는 형태이다. (1개 서버, N개 서비스)
이 때 1번의 형태로 하면 동시에 1개의 터널만 os daemon 으로 동작시킬 수 있다는 제약이 있다. 즉 서버가 재부팅되거나 하는 경우, 매번 각 터널을 수동으로 열어주어야 한다는 뜻이다.
2번으로 구성하면 홈서버가 재시작해도 서비스별로 컨테이너가 자동으로 뜨게 해두면 N개의 서로 구분되는 터널이 서비스별로 매번 새로 뜨고 자동으로 연결도 복구시켜주므로 홈서버 재구동이 필요할 때 발생하는 복구과정을 손쉽게 할 수 있다.
터널을 생성하는 2가지 방법
터널을 만드는 것에도 2가지 방법이 있다.
- Cloudflare 웹에서 제공하는 Dashboard를 이용하는 방법 (👍추천)
- cloudflared CLI를 이용하는 방법
내가 2가지 방법을 모두 써봤는데 2번이 쉬울거라 예상해서 그쪽으로 시도했다가, 막상 해보니 1번이 새로 터널을 여는 난이도가 쉽고 관리도 용이했으므로 1번 방식으로 설명한다.
각 항목마다 사진에 붉은색 박스 혹은 화살표를 통해 어떤 부분을 봐야하는지 도움이 되길 바라며 포인팅 해두었다.
1. 터널 생성
cloudflare zero trust 대쉬보드 > 네트워크 > tunnels > 터널생성

2. 터널 유형 선택
Cloudflared 로 선택

3. 터널 이름 지정
예시에서는 blog 로 지정

4. 터널 구성
- 환경 선택에서 Docker를 선택
별다른 문제가 없다면, cloudflare 설정화면 하단에 커넥터 id와 상태가 연결됨
으로 뜨는 것을 확인할 수 있다.

터널에 복사된 내용을 붙이면 아래와 같이 container 이미지를 받고 바로 컨테이너로 뜨는 걸 확인할 수 있다.

- 여기까지는 연결성 테스트에 성공한 것으로, 이 내용은 docker compose로 다시 변경해야 한다. 이 작업은 6. docker-compose.yml 작성 파트에서 설명한다.

5. 트래픽 라우팅 설정
연결 이후 다음 버튼을 누르면 트래픽 라우팅 설정 페이지로 온다.
아래는 예시 설정이다.
- 서브도메인을 blog.hamsterapp.net 으로 설정
- 설정 이후 외부에서 https://blog.hamsterapp.net 으로 유저가 접속하면, 해당 요청은 클라우드 플레어의 터널을 통해 PC 내부로 들어와
http://localhost:8080
에 도달하게 된다. 즉 PC 내부에서localhost:8080
으로 제공하는 서비스와 연결될 것으로 기대할 수 있다. - 다만, 지금은 위 4번 작업 수행시
docker run
명령을 붙여넣을 때network
옵션을host
로 지정했어야 하지 않았으므로, 이 시점에서cloudflared
는docker container
의 분리된 네트워크를 사용한다. 따라서localhost:8080
으로 제공하는 서비스가 있다고 해도 연결이 안된다.
내부에서는 http://localhost:8080 으로 연결

6. docker-compose.yml 작성
기존의 docker-compose.yml
파일에, 아래의 tunnel 서비스를 추가한다.
tunnel:
container_name: cloudflared-tunnel
image: cloudflare/cloudflared:latest
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=<위에서 복사된 token>
아래는 frontend
라는 서비스가 이미 구성되어있던 docker-compose.yml
파일을 예시로, tunnel
서비스를 추가하면 다음과 같이 보인다.

이 경우, docker compose 의 frontend
서비스는 같은 compose 네트워크 내에서 http://frontend:80
으로 연결할 수 있다. 그러므로 같은 compose 네트워크 안에 속한 tunnel
서비스가 접근하기 위해, 앞에서 트래픽 라우팅으로 설정한 http://localhost:8080
값을 http://frontend:80
로 변경해야 한다.
예시에서는 environment 에 토큰을 직접 적어넣었지만, docker compose로 운영할 땐 .env 파일을 통해 해당 값을 동적으로 주입할 수 있다. 그러면 docker-compose.yml 도 소스코드에 포함시켜 업로드해도 안전하다.
7. 터널 라우팅 수정하기
여기서 위에서 설정했던 라우팅 경로값을 변경할 수 있다.

이후 공개호스트이름 > 메뉴 > 편집 을 통해 편집메뉴로 들어가면

cloudflare zero trust 대쉬보드 > 네트워크 > tunnels > 터널 > blog > 우측 메뉴판 > 구성 으로 들어간다

8. 최종확인하기
위에서 설정한 서브도메인에 접속하여, 내가 제공하는 서비스가 제대로 연결되는지 확인해보자.
디버깅
제대로 연결이 되었다면 내 서비스가 보일 것이다.
연결이 안되는 경우라면 아래 2가지를 먼저 점검하자
- cloudflared 가 제대로 뜨긴 했지만, 내부 서비스 연결에 실패한 경우 -> 내부에서 서비스를 제공하는 포트를 잘못입력하는 경우가 대부분으로 5,6,7 번 과정을 다시 보면서 내 웹서비스가 어느 포트로 서비스를 제공하고 있는지, cloudflared 가 그 포트를 바라보고 있는지 점검한다.
- 홈서버의 cloudflared 가 제대로 뜨지 못한 경우. 이 경우에는 cloudflared 가 제대로 떠있는지 확인하고 조치하면 된다.
자 이제 홈서버에서 웹서비스를 편하게 제공하자.
Member discussion: