Skip to content

fix: route wildcard cert to DNS-01 issuer so apex SAN avoids HTTP-01 loop - #39

Closed
krist7599555 wants to merge 1 commit into
deploys-app:mainfrom
krist7599555:fix/wildcard-apex-dns01
Closed

fix: route wildcard cert to DNS-01 issuer so apex SAN avoids HTTP-01 loop#39
krist7599555 wants to merge 1 commit into
deploys-app:mainfrom
krist7599555:fix/wildcard-apex-dns01

Conversation

@krist7599555

@krist7599555 krist7599555 commented Aug 19, 2026

Copy link
Copy Markdown

Caution

This is vibe code, and not test it yet

Fixes #38

ปัญหา

wildcard Certificate (k8s/cert.go) ครอบ 2 SAN: *.<domain> กับ apex <domain> เปล่า ๆ

cert-manager auto-filter HTTP-01 solver เฉพาะ *.<domain> SAN เท่านั้น (Let's Encrypt ไม่ให้ใช้ HTTP-01 กับ wildcard) ส่วน apex SAN ยังไปหยิบ HTTP-01 (parapet ingress) solver ของ Issuer letsencrypt ที่ใช้ร่วมกัน

สำหรับ domain ที่ proxy ผ่าน Cloudflare/CDN → apex HTTP-01 challenge ไม่มีทางผ่าน (request โดน redirect/404 ที่ edge ไม่ถึง parapet solver) → cert-manager retry ไม่จบ

เจอกับ domain จริง: ยิงทุก ~10 วิ, ~17k /.well-known/acme-challenge/ requests/วัน ที่ fail ทั้ง apex และ www ทดสอบ edge:

http://<domain>/.well-known/acme-challenge/<t>   → 301 (Always Use HTTPS)
http://www.<domain>/.well-known/acme-challenge/<t> → 404
https://<domain>/.well-known/acme-challenge/<t>  → 301 (apex→www)

Root cause

083969d (#5) ตอนแรกชี้ wildcard rows ไป DNS-01 ClusterIssuer แยก แล้วมี commit "simplify" เปลี่ยนกลับมาใช้ Issuer letsencrypt ตัวเดียว โดยให้เหตุผลว่า "cert-manager filters HTTP-01 ... for wildcard SANs, so wildcard challenges naturally route to the Cloud DNS solver" — ซึ่งจริงเฉพาะ *.<domain> แต่ไม่จริงกับ apex SAN → เป็นที่มาของ loop

วิธีแก้

pin wildcard rows ไปที่ ClusterIssuer letsencrypt-dns01 (DNS-01 ล้วน — ตัวที่ #5 อ้างถึงตอนแรก) เพื่อให้ ทั้ง apex และ wildcard SAN validate ผ่าน DNS-01 ส่วน non-wildcard เหมือนเดิม (letsencrypt, Issuer)

issuerRef := cmmeta.ObjectReference{Name: "letsencrypt", Kind: v1.IssuerKind}
if obj.Wildcard {
    dnsNames = append(dnsNames, "*."+obj.Domain)
    issuerRef = cmmeta.ObjectReference{Name: "letsencrypt-dns01", Kind: v1.ClusterIssuerKind}
}

⚠️ หมายเหตุตอน deploy

โค้ดนี้อ้าง ClusterIssuer letsencrypt-dns01 ซึ่ง commit "simplify" เอาออกไปโดยบอกว่า "a ClusterIssuer that doesn't need to exist"ต้องมี issuer ตัวนี้อยู่ใน cluster (DNS-01 solver, config Cloud DNS / CNAME delegation เดียวกับ DNS-01 solver ของ Issuer letsencrypt) ถึงจะทำงาน

ถ้าอยากใช้ Issuer ตัวเดียวต่อ อีกทางเลือกคือขยาย selector ของ DNS-01 solver ใน Issuer letsencrypt ให้ match apex identifier ด้วย — จะปรับ PR เป็นแบบไหนก็บอกได้ครับ

Verification

  • go build ./k8s/ ผ่าน
  • gofmt clean

🤖 Generated with Claude Code

A wildcard Certificate covers both `*.<domain>` and the bare apex
`<domain>`. cert-manager auto-filters the HTTP-01 solver only for the
`*.<domain>` SAN (Let's Encrypt rejects HTTP-01 for wildcards); the apex
SAN still selects the shared `letsencrypt` Issuer's HTTP-01 (parapet
ingress) solver.

For a Cloudflare/CDN-proxied domain that HTTP-01 challenge can never
complete — the request is redirected/404'd at the edge and never reaches
the parapet solver — so cert-manager retries it indefinitely (observed
~10s cadence, ~17k failed /.well-known/acme-challenge/ requests/day).

Pin wildcard rows to the DNS-01-only ClusterIssuer letsencrypt-dns01 (the
issuer the original deploys-app#5 change referenced before the "reuse letsencrypt"
simplification) so both the apex and wildcard SANs validate via DNS-01.

Fixes deploys-app#38
@krist7599555
krist7599555 force-pushed the fix/wildcard-apex-dns01 branch from 637c382 to b5a36f3 Compare August 19, 2026 17:21

@acoshift acoshift left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

เดี๋ยวผมแก้โดยใช้วิธีอื่นแทนครับ
ใน cluster เราใช้ issuer ตัวเดียว ที่แยก selector ไว้ ไม่ได้แบ่ง http กับ dns issuer

Comment thread k8s/cert.go
// DNS-01 for every SAN (apex included) — avoids the HTTP-01 solver that
// never validates behind a CDN. See the Wildcard field comment above.
issuerRef = cmmeta.ObjectReference{
Name: "letsencrypt-dns01",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

บน cluster ไม่มี issuer นี้ครับ

@krist7599555

Copy link
Copy Markdown
Author

ปิด PR เนื่องจากมีวิธีที่เหมาะสมกว่าจาก maintainer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cert-manager uses HTTP-01 for apex SAN of Wildcard cert → loops forever on Cloudflare/CDN-proxied domains

2 participants