운영에서 test-deploy.qeploy.com 으로 도메인 연결을 처음 끝까지 돌려보다 확인했다.
연결 자체는 성공한다. 그런데 인증서가 영원히 PENDING 에 머문다.
관측
|
값 |
우리 DB status |
CONNECTED |
우리 DB certificateStatus |
PENDING |
우리 DB httpsEnforced |
false |
GitHub Pages status |
errored |
GitHub Pages https_certificate |
none |
https://test-deploy.qeploy.com/ |
200 (에셋도 200) |
dig test-deploy.qeploy.com |
172.67.195.73, 104.21.92.152 ← Cloudflare IP |
원인
cloudflare.proxied: true 다. 세 프로파일 모두 하드코딩된 기본값이고 환경변수로 뺀 적도 없다.
# application.yaml / application-dev.yml / application-prod.yml
cloudflare:
...
proxied: true
프록시가 켜져 있으면 DNS 가 Cloudflare IP 로 응답한다. 그래서 GitHub 이 CNAME 이 자기(dldnsgkr.github.io)를 가리키는지 검증할 수 없고, Let's Encrypt 인증서를 발급하지 못한다. GitHub 쪽 상태가 errored 로 남는 이유가 이것이다.
지금 브라우저에서 HTTPS 가 200 인 것은 Cloudflare 엣지 인증서(*.qeploy.com) 덕분이다. 사용자 눈에는 정상이지만 엣지→오리진 구간은 GitHub 인증서 없이 돈다.
구조적으로, 관리형 서브도메인을 쓰는 한 certificateStatus 는 절대 ACTIVE 가 되지 않고 httpsEnforced 도 계속 false 다. checkVerification 을 몇 번 호출해도 마찬가지다 — GitHub 이 발급을 못 하는 것이지 우리가 덜 기다린 게 아니다.
선택지 (제품 결정)
A. 프록시 유지 (현상 유지)
- 사용자 경험은 지금도 정상 — HTTPS 200, Cloudflare 캐싱·DDoS 보호 유지
- 대신
certificateStatus / httpsEnforced 필드가 영원히 의미 없는 값이 된다. 화면에 그대로 노출하면 "인증서 발급 중"이 끝나지 않는 것처럼 보인다
- 이 길을 택하면 두 필드를 GitHub Pages 대상에서는 표시하지 않거나, 상태 문구를 바꿔야 한다
B. 관리형 서브도메인은 DNS only 로 생성 (회색 구름)
- GitHub 이 검증·발급에 성공해
certificateStatus 가 실제 값으로 채워진다
- 대신 Cloudflare 캐싱·DDoS 보호가 빠지고, 오리진이 GitHub Pages 라는 것이 노출된다
proxied 를 하드코딩 대신 hostingTarget 별로 갈라야 한다 (GITHUB_PAGES → false, AWS/GCP → 기존대로)
C. 프록시 유지 + CF SSL 모드 명시
- Full(strict) 로 두려면 오리진 인증서가 필요한데 GitHub Pages 는 그걸 줄 수 없다 → Flexible/Full 이 되고, 엣지→오리진 구간이 평문이거나 검증 없이 도는 것을 받아들이는 선택
개인적으로는 B 가 맞다고 본다. GitHub Pages 를 오리진으로 쓰면서 프록시를 켜는 조합은 인증서 경로가 성립하지 않는다. 다만 캐싱·보호를 포기하는 결정이라 제품 쪽에서 정해야 한다.
재현
NOT_BOUND 아닌 프로젝트에 GitHub Pages 배포를 끝낸다
- 에이전트에 "
<sub>.qeploy.com 도메인을 연결해줘" 라고 요청하고 DOMAIN_BINDING 승인
POST /api/v1/domains/{id}/verification-checks 호출 → status: CONNECTED, certificateStatus: PENDING
gh api repos/<owner>/<repo>/pages → status: errored, https_certificate: none
참고
- 실측 도메인:
test-deploy.qeploy.com (프로젝트 11 / dldnsgkr/prod-flow-check)
- Cloudflare 레코드 ID:
a6ba7e24f2cf9cf49b31beff73af9d62
- 테스트가 끝나면 이 레코드는 정리 대상이다
운영에서
test-deploy.qeploy.com으로 도메인 연결을 처음 끝까지 돌려보다 확인했다.연결 자체는 성공한다. 그런데 인증서가 영원히
PENDING에 머문다.관측
statusCONNECTEDcertificateStatusPENDINGhttpsEnforcedfalsestatuserroredhttps_certificatenonehttps://test-deploy.qeploy.com/dig test-deploy.qeploy.com172.67.195.73,104.21.92.152← Cloudflare IP원인
cloudflare.proxied: true다. 세 프로파일 모두 하드코딩된 기본값이고 환경변수로 뺀 적도 없다.프록시가 켜져 있으면 DNS 가 Cloudflare IP 로 응답한다. 그래서 GitHub 이 CNAME 이 자기(
dldnsgkr.github.io)를 가리키는지 검증할 수 없고, Let's Encrypt 인증서를 발급하지 못한다. GitHub 쪽 상태가errored로 남는 이유가 이것이다.지금 브라우저에서 HTTPS 가 200 인 것은 Cloudflare 엣지 인증서(
*.qeploy.com) 덕분이다. 사용자 눈에는 정상이지만 엣지→오리진 구간은 GitHub 인증서 없이 돈다.구조적으로, 관리형 서브도메인을 쓰는 한
certificateStatus는 절대ACTIVE가 되지 않고httpsEnforced도 계속false다.checkVerification을 몇 번 호출해도 마찬가지다 — GitHub 이 발급을 못 하는 것이지 우리가 덜 기다린 게 아니다.선택지 (제품 결정)
A. 프록시 유지 (현상 유지)
certificateStatus/httpsEnforced필드가 영원히 의미 없는 값이 된다. 화면에 그대로 노출하면 "인증서 발급 중"이 끝나지 않는 것처럼 보인다B. 관리형 서브도메인은 DNS only 로 생성 (회색 구름)
certificateStatus가 실제 값으로 채워진다proxied를 하드코딩 대신hostingTarget별로 갈라야 한다 (GITHUB_PAGES→ false, AWS/GCP → 기존대로)C. 프록시 유지 + CF SSL 모드 명시
개인적으로는 B 가 맞다고 본다. GitHub Pages 를 오리진으로 쓰면서 프록시를 켜는 조합은 인증서 경로가 성립하지 않는다. 다만 캐싱·보호를 포기하는 결정이라 제품 쪽에서 정해야 한다.
재현
NOT_BOUND아닌 프로젝트에 GitHub Pages 배포를 끝낸다<sub>.qeploy.com도메인을 연결해줘" 라고 요청하고DOMAIN_BINDING승인POST /api/v1/domains/{id}/verification-checks호출 →status: CONNECTED,certificateStatus: PENDINGgh api repos/<owner>/<repo>/pages→status: errored,https_certificate: none참고
test-deploy.qeploy.com(프로젝트 11 /dldnsgkr/prod-flow-check)a6ba7e24f2cf9cf49b31beff73af9d62