← 목록

Cloudflare Tunnel, 설정 파일을 고쳐도 반영이 안 되던 이유

#cloudflare#tunnel#traefik#self-hosting

홈 서버에 SSO 담당할 authentik 이랑 위키로 쓸 Outline 을 올렸고, 이제 서브도메인 두 개를 공개하는 일만 남아 있었다. 우리 서버는 포트를 하나도 안 열고 Cloudflare Tunnel로만 트래픽 받는 구조라서 터널의 ingress 설정에 호스트네임만 추가하면 되는 작업이었다. 그런데 여기서 헤매갖고 정리해둠

파일을 고쳤는데 404가 나온다

몇 달 전 터널을 처음 구축할 때는 전부 파일로 했다. config.yml에 호스트네임별 라우팅을 적고 cloudflared를 재시작하는 방식이다. 이번에도 똑같이 했다. ingress에 두 항목을 추가하고, 문법 검증까지 통과시키고, 컨테이너를 재시작했다.

그런데 404가 나온다. DNS 레코드도 만들었고, 뒤에 있는 traefik은 내부에서 테스트하면 멀쩡하게 응답한다. 터널만 통과하면 404다. 그러니까 cloudflared가 이 호스트네임을 모른다는 얘기다.

로그를 다시 읽어보니

cloudflared 로그를 처음부터 다시 읽었다. 기동 직후에 이런 줄이 있었다.

INF Updated to new configuration config="{...ingress:[...]}" version=1

기동하면서 설정을 어디선가 새로 받아왔다는 뜻이다. 그리고 그 설정 안에 찍힌 ingress 목록을 보니 내가 파일에 추가한 호스트네임이 없다. 반대로 로컬 config.yml에는 없는 옛날 호스트네임이 이 목록에는 들어있었다. 파일에 없는게 돌고 있고 파일에 있는게 안 돌고 있으니, 이 터널은 더 이상 내 파일을 안 읽는다는 결론이 나온다.

찾아보니 Cloudflare Tunnel에는 관리 방식이 두 가지가 있다.

  • 로컬 관리(locally-managed): 서버의 config.yml을 읽는다. 내가 처음 구축했던 방식임
  • 원격 관리(remotely-managed): 설정을 Cloudflare 쪽에 저장해두고 대시보드나 API로 고친다. 터널이 기동할 때 Cloudflare에서 설정을 내려받고, 로컬 파일은 무시한다.

위 로그가 바로 원격 설정을 내려받는 장면이었음

그런데 우리 터널은 분명히 로컬 관리로 만들었었다. 왜 넘어갔지. 아마 AI한테 맡긴게 문제였을것 같다. 어쨋든 전환하는 순간 Cloudflare가 로컬 파일 내용을 원격 설정으로 복사해가고, 그때부터는 파일을 아무리 고쳐도 반영이 안된다. 참고로 한번 전환하면 같은 터널을 로컬 관리로 되돌리는 기능은 없다.

증상이 묘했던 이유도 여기서 설명이 된다... 기존 서비스는 전부 멀쩡했는데, 전환 시점의 설정이 원격에 그대로 복사돼 있었기 때문이다. 새로 추가한 것만 조용히 무시되고 있던 거였다

이번엔 502

원인을 알았으니 대시보드에서 라우트를 추가했다. 그랬더니 이번엔 502 Bad Gateway가 나온다. 로그를 보면 이렇다.

ERR error="... tls: failed to verify certificate:
x509: certificate is valid for *.moon-core.com, moon-core.com, not lab-traefik"

터널 뒤에는 traefik이 리버스 프록시로 서 있고, cloudflared는 traefik에 https로 붙으면서 인증서를 검증한다. traefik이 내미는 인증서는 *.moon-core.com 와일드카드인데, 라우트에 적힌 접속 주소가 https://lab-traefik:443(도커 컨테이너 이름)이라서 이름이 안 맞는다. 그래서 검증에 실패하고 502가 나는 것이다.

그러면 예전에는 어떻게 됐던걸까? 옛 config.yml을 열어보니 답이 있었다.

- hostname: www.moon-core.com
  service: https://lab-traefik:443
  originRequest:
    originServerName: www.moon-core.com   # 인증서에서 이 이름을 기대해라
    caPool: /etc/ssl/certs/cloudflare-origin-ca.pem

originServerName이 핵심이다. 접속 주소와 별개로 인증서 검증에 쓸 이름을 지정하는 옵션인데, 처음 구축할 때 호스트네임마다 꼬박꼬박 적어놨었다. 원격으로 복사된 옛 라우트들은 이 값까지 같이 넘어가서 멀쩡했고, 대시보드에서 새로 만든 라우트에는 이게 빠져있어서 502가 난 것이다.

대시보드에서 이 옵션을 찾는 것도 일이었다. 2026년 2월부터 메인 대시보드에도 터널 메뉴가 생겼는데(Networking > Tunnels) 여기 라우트 편집 화면에는 기본 항목만 나온다. 고급 TLS 설정은 Cloudflare One 쪽 화면에만 있다. Networks > Connectors > Cloudflare Tunnels에서 터널을 열고, Published application routes 탭에서 앱을 편집하면 아래에 Additional application settings가 접혀있고, 그 안의 TLS 섹션에 Origin Server Name 칸이 있다. 같은 데이터를 두 UI가 보여주는데 한쪽만 전체 옵션을 노출하는 구조라서, 새 UI만 보면 이 설정이 있는지도 알 수가 없다.

라우트마다 Origin Server Name에 자기 호스트네임을 넣어주니 전부 열렸다. 참고로 CA 풀은 안 넣어도 됐다. Cloudflare Origin CA 인증서를 cloudflared 컨테이너의 /etc/ssl/certs/에 마운트해뒀는데, cloudflared가 Go로 짜여있어서 그 디렉토리를 시스템 신뢰 저장소로 읽어 자동으로 신뢰하기 때문이다.

설정의 원본이 서버 밖에 있다는 문제

파일 관리로 돌아갈지 고민했다. 같은 터널을 되돌리는 방법은 없지만 새 터널을 로컬 관리로 만들어서 갈아타면 되기는 한다. 그런데 터널 설정이 자주 바뀌는것도 아니고, 대시보드에서 한눈에 보이는 편의도 있어서 그냥 원격 관리를 유지하기로 했다. 대신 세 가지를 해뒀다.

  1. 이제 안 읽히는 config.yml 맨 위에 경고 주석을 달았다. 나중에 이 파일을 열어볼 사람(아마 미래의 나)이 같은 삽질을 반복하지 않도록.
  2. Cloudflare Tunnel:Edit 권한만 가진 API 토큰을 발급했다. 라우트 추가 같은 변경을 대시보드에서 클릭하는 대신 API 호출로 처리하기 위해서다. UI는 계속 바뀌는데 API는 안 바뀌니까.
  3. 원격 설정을 매일 서버로 백업하는 스크립트를 cron에 걸었다. 설정 API를 조회해서 내용이 바뀌었을 때만 JSON으로 저장한다. 원격 관리의 약점이 설정의 원본이 서버 밖에 있다는 것인데, 스냅샷이 서버에 쌓이면 이력 추적도 되고 최악의 경우 복원 자료도 된다.

정리

  • cloudflared 로그에 Updated to new configuration ... version=N이 찍히면 그 터널은 원격 관리다. 로컬 config.yml은 무시된다.
  • 로컬에서 원격으로 전환은 대시보드에서 프롬프트 한 번 수락하면 일어나고, 되돌릴 수 없다. 전환 시점의 파일 내용은 원격으로 복사된다.
  • 터널 뒤에 리버스 프록시를 두고 https로 붙는다면 라우트마다 Origin Server Name을 인증서와 맞는 이름으로 지정해줘야 한다. 도커 컨테이너 이름으로 접속하면 이름이 안 맞아서 502가 난다.
  • 이 설정은 메인 대시보드의 새 터널 UI에는 없고 Cloudflare One의 라우트 편집 화면에만 있다.
  • 원격 관리를 쓰기로 했다면 설정 백업은 직접 챙겨야 한다. 서버에는 아무것도 안 남는다.
← 목록으로
오늘 0·전체 0