stamper
CLI개인서버CloudflareTunnelHTTPS

개인 서버 구축 4: 도메인·Cloudflare Tunnel·HTTPS를 연결하는 CLI 프롬프트

개발자김철수1시간 전조회 2추천 0
변수 입력9
변수를 채운 뒤 완성본을 복사하세요

이번 단계의 목표

별도로 구매한 domain을 Cloudflare에 연결하고, Cloudflare Tunnel을 통해 집 안의 localhost web service를 HTTPS hostname으로 공개한다. inbound port forwarding 없이 server가 Cloudflare로 outbound tunnel을 만드는 구조다.

방문자 browser
  -> Cloudflare DNS·edge HTTPS
  -> Cloudflare Tunnel
  -> 집 서버의 cloudflared
  -> http://127.0.0.1:{{ORIGIN_PORT}}
  -> Docker web service

관리자 notebook
  -> Tailscale
  -> SSH
  -> 집 서버

공개 웹 경로와 관리 경로를 섞지 않는다. SSH, database, Docker socket, admin dashboard는 public hostname으로 내보내지 않는다. 내부 관리 웹이 꼭 필요하다면 Cloudflare Access의 identity 정책을 별도로 적용한다.

준비할 정보

  • {{DOMAIN}}: 구매한 apex domain. 실제 값은 DNS 설정 시에만 사용한다.
  • {{PUBLIC_HOSTNAMES}}: 예: app.example.com, api.example.com
  • {{ORIGINS}}: 예: http://127.0.0.1:3000, http://127.0.0.1:8080
  • {{REGISTRAR}}: domain을 구매한 registrar
  • {{TUNNEL_NAME}}: 용도를 알 수 있는 이름
  • {{ACCESS_REQUIRED}}: 공개하면 안 되는 hostname과 허용 identity 조건
  • {{APP_CONFIG}}: CORS, allowed host, callback URL, cookie domain 등 외부 URL 의존 설정

domain 이전과 DNS 주의사항

Cloudflare를 authoritative DNS로 사용할 때 registrar의 nameserver를 변경한다. 기존 MX, TXT, CAA, verification record를 빠뜨리면 email이나 다른 서비스가 중단될 수 있으므로 현재 zone을 먼저 내보내고 비교한다. domain 등록기관 자체를 옮기는 작업은 이 단계에 필요하지 않다.

복사해서 쓰는 CLI agent 프롬프트

개인 서버의 web service를 {{DOMAIN}}과 Cloudflare Tunnel로 안전하게 공개해줘.

공개 hostname: {{PUBLIC_HOSTNAMES}}
내부 origin: {{ORIGINS}}
registrar: {{REGISTRAR}}
tunnel 이름: {{TUNNEL_NAME}}
Access 보호 대상: {{ACCESS_REQUIRED}}
application URL 설정: {{APP_CONFIG}}

작업 규칙:
1. 현재 DNS record를 read-only로 목록화하고 MX, TXT, CAA, 기존 subdomain 의존성을 분류해. nameserver 변경 전에 누락 위험과 TTL 전파 계획을 보고해.
2. domain 구매와 Cloudflare zone 추가, registrar nameserver 변경, zone 활성화 확인을 단계별로 분리해. registrar 로그인·결제·domain transfer는 자동 실행하지 마.
3. Cloudflare dashboard에서 remotely-managed tunnel을 만들고 서버 OS용 공식 설치 명령을 사용해. tunnel token은 secret이므로 화면·shell history·process report·Git·compose file에 노출하지 마.
4. service URL은 실제로 검증된 `http://127.0.0.1:port`를 사용해. 임의의 container IP처럼 재시작 시 바뀌는 주소를 고정하지 마.
5. hostname별 origin mapping을 표로 보여주고 하나씩 추가해. wildcard, catch-all, apex 공개는 요구가 없으면 만들지 마.
6. SSH, DB, cache, Docker daemon, metrics, admin port를 public application route로 만들지 마.
7. 비공개 관리 웹은 Cloudflare Access application과 deny-by-default policy를 먼저 설계해. 우회 가능한 별도 hostname이나 origin의 LAN·공인 bind가 없는지도 확인해.
8. TLS mode, redirect, WebSocket, request size, timeout을 application 요구와 비교해. edge HTTPS가 된다는 이유로 origin의 불필요한 외부 노출을 허용하지 마.
9. CORS allowed origins, OAuth callback, secure cookie, proxy header trust는 정확한 hostname만 추가해. 모든 origin 허용이나 모든 proxy 신뢰로 해결하지 마.
10. DNS 또는 tunnel 설정을 바꾸기 전 변경 전 record와 rollback 절차를 저장하고 승인을 받아.
11. 적용 후 public DNS, HTTPS certificate, response header, application health, tunnel service 재부팅 복구를 검증해. secret·cookie·개인정보가 포함된 response는 저장하지 마.

결과는 '현재 DNS 영향 / 목표 traffic flow / hostname-origin 표 / Cloudflare zone / tunnel 설치 / Access 정책 / application 설정 / 검증 / rollback / 남은 공개면' 순서로 작성해.

검증 예시

# DNS가 기대한 곳에서 응답하는지 확인
dig +short {{PUBLIC_HOSTNAME}}

# 인증서와 redirect를 포함한 외부 응답 확인
curl -I https://{{PUBLIC_HOSTNAME}}

# origin은 서버 내부에서만 확인
curl --fail --silent --show-error http://127.0.0.1:{{ORIGIN_PORT}}/health

# tunnel service와 실제 listening port 확인
systemctl status cloudflared --no-pager
sudo ss -lntup

curl -I만으로 application의 전체 기능이 검증되는 것은 아니다. 로그인, API, upload, WebSocket, OAuth가 있다면 실제 사용자 흐름을 별도 smoke test로 확인한다.

통과 기준

  • 외부에서 https://{{PUBLIC_HOSTNAME}} 접속과 인증서 검증이 성공한다.
  • router에는 새 inbound forwarding 또는 DMZ 설정이 없다.
  • origin port는 공인·LAN interface가 아니라 localhost 또는 의도한 private network에만 bind한다.
  • cloudflared 재시작과 서버 재부팅 후 tunnel이 Healthy로 복구된다.
  • 보호 대상 hostname은 로그아웃 상태에서 차단되고 허용 identity만 접근한다.
  • 기존 email과 DNS 기반 서비스가 nameserver 변경 뒤에도 정상이다.

즉시 중단할 조건

  • 기존 DNS record backup 없이 nameserver를 변경하려 한다.
  • tunnel token이 commit, issue, log, screenshot에 노출됐다.
  • 편의를 위해 SSH·DB·admin port를 public hostname으로 연결하려 한다.
  • application 오류를 해결하려고 CORS *, proxy 전체 신뢰, 인증 해제를 제안한다.

공식 자료

댓글 0

아직 댓글이 없습니다.