SSD Nodes Learn
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-07-24

วิธีใช้ Certbot ออก Wildcard Certificate

เรียนรู้วิธีออก Wildcard Certificate ด้วย Certbot ผ่าน DNS-01 challenge แนะนำการใช้ DNS plugin เพื่อให้การต่ออายุ TXT record เป็นไปอย่างอัตโนมัติ

ทำไม wildcard certificate จึงต้องใช้ DNS-01

Wildcard certificate ครอบคลุมทุก subdomain ในระดับแรกของโดเมน: *.example.com จะครอบคลุมทั้ง app.example.com, blog.example.com และชื่ออื่น ๆ ที่มีเพียงหนึ่ง label Let's Encrypt ออก wildcard certificates ผ่านทาง DNS-01 challenge เท่านั้น ดังนั้น Certbot จึงต้องพิสูจน์ความเป็นเจ้าของ DNS ของโดเมน โดยการสร้าง TXT record ที่ _acme-challenge.example.com การใช้ HTTP-01 challenge ไม่สามารถใช้งานได้ เนื่องจากกระบวนการส่งไฟล์ token เป็นเพียงการพิสูจน์ความเป็นเจ้าของ hostname เดียว ซึ่งก็คือ hostname ที่ server ตรวจสอบเรียกใช้ไฟล์นั้น Wildcard คือการยืนยันสิทธิ์สำหรับทุกชื่อที่เป็นไปได้ภายใต้โดเมน และ DNS เป็นเพียงระบบเดียวที่มีข้อมูลสาธารณะที่ครอบคลุมทั้ง namespace

ข้อกำหนดนี้ส่งผลต่อขั้นตอนอื่น ๆ ทั้งหมดในหน้านี้ การจะผ่าน DNS-01 ได้ คุณต้องสามารถสร้าง TXT records ใน zone ของโดเมนได้ ไม่ว่าจะเป็นการทำด้วยตนเองหรือผ่าน API ของผู้ให้บริการ DNS การทำด้วยตนเองจะใช้งานได้เพียงครั้งเดียวและจะล้มเหลวเมื่อต้องต่ออายุเนื่องจากสาเหตุที่ระบุไว้ด้านล่าง ส่วนการใช้งานผ่าน API ด้วย Certbot DNS plugin จะสามารถต่ออายุได้โดยอัตโนมัติ ซึ่งเป็นวิธีการที่ควรเลือกใช้

เนื้อหานี้เป็นส่วนของ wildcard ในคู่มือ Certbot ของเรา สำหรับการใช้งาน certificate แบบ hostname เดียว การตั้งค่า web server และกฎของ port 80 สามารถอ่านเพิ่มเติมได้ที่ Certbot with nginx on Ubuntu 24.04 และ Certbot with Apache on Ubuntu 24.04

การทำงานของ _acme-challenge TXT record

เมื่อ Certbot ส่งคำขอ *.example.com Let's Encrypt จะตอบกลับด้วย token แบบสุ่ม Certbot จะนำ token นั้นมาผสมกับ account key ของ ACME (automatic certificate management environment) จากนั้นจึงทำการ hash ผลลัพธ์ด้วย SHA-256 เพื่อสร้างค่าข้อความสั้นๆ ค่าดังกล่าวต้องปรากฏเป็น TXT record ที่ _acme-challenge.example.com จากนั้น Let's Encrypt จะตรวจสอบ authoritative name servers ของโดเมนคุณผ่านโครงสร้างพื้นฐานของตนเอง หากค่าที่อ่านได้ตรงกับค่าที่คาดหวัง แสดงว่าคุณได้พิสูจน์แล้วว่าคุณเป็นผู้ควบคุม zone นั้น และการควบคุม zone จะถือว่าเป็นการควบคุมทุกชื่อที่อยู่ภายใต้ zone ดังกล่าว

สาเหตุหลักที่ทำให้เกิดความล้มเหลวมี 2 ประการ:

  • การขอ example.com และ *.example.com ในใบรับรองใบเดียวกัน หมายถึงการทำ challenge แยกกันสองรายการ และ TXT record ทั้งสองจะอยู่ที่ชื่อเดียวกันคือ _acme-challenge.example.com ทั้งสองค่าต้องมีอยู่พร้อมกัน การเพิ่ม record ที่สองเข้าไปนั้นถูกต้อง แต่การแทนที่ record แรกด้วย record ที่สองจะทำให้การทำ challenge แรกล้มเหลว
  • การตรวจสอบจะอ่านข้อมูลจาก authoritative servers แต่แผงควบคุมของผู้ให้บริการอาจใช้เวลาหนึ่งนาทีหรือมากกว่าในการส่ง record ใหม่ไปยัง server เหล่านั้น ควรตรวจสอบจากภายนอกก่อนเริ่มกระบวนการ validation:
dig +short TXT _acme-challenge.example.com @1.1.1.1

เมื่อคำสั่งแสดงค่าที่ Certbot ร้องขอ การตรวจสอบจึงจะสำเร็จ หากคำสั่งไม่แสดงผลใดๆ ให้รอแล้วจึงรันคำสั่งใหม่อีกครั้ง

ทดสอบการทำงานด้วยตนเอง: manual mode

Manual mode บังคับให้คุณแก้ไข DNS ด้วยตนเอง วิธีนี้เป็นวิธีที่ดีที่สุดในการทำความเข้าใจกลไกก่อนที่จะเริ่มใช้ระบบอัตโนมัติ:

sudo certbot certonly --manual --preferred-challenges dns -d example.com -d '*.example.com'

เครื่องหมายคำพูดรอบ wildcard ช่วยป้องกันไม่ให้ shell ประมวลผล * เป็นรูปแบบชื่อไฟล์ (filename pattern) จากนั้น Certbot จะหยุดรอพร้อมคำแนะนำ:

Please deploy a DNS TXT record under the name:
_acme-challenge.example.com.
with the following value:
Jx9mQ2wLr8vTn5cKp0aYdG3hB7fZs4eN1oiRuXqMk6E

สร้าง TXT record ดังกล่าวในแผงควบคุมของผู้ให้บริการ DNS ของคุณ ตรวจสอบให้แน่ใจว่า record ปรากฏขึ้นแล้วด้วยคำสั่ง dig ด้านบน แล้วจึงกด Enter เนื่องจากคำสั่งนี้มีการขอทั้ง bare domain และ wildcard ทำให้ Certbot จะแจ้งเตือนสองครั้ง ให้คง record ทั้งสองไว้จนกว่าการออกใบรับรองจะเสร็จสิ้น เมื่อสำเร็จจะปรากฏข้อความดังนี้:

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem

ทำไม manual mode จึงไม่สามารถต่ออายุได้ด้วยตัวเอง

การต่ออายุแต่ละครั้งคือกระบวนการใหม่ที่ต้องใช้ token ใหม่ ดังนั้นค่า TXT จะเปลี่ยนไปทุกครั้ง ข้อมูล record ที่คุณคัดลอกมาในวันนี้จะไม่สามารถใช้งานได้อีกเมื่อผ่านไป 60 วัน ตัวจับเวลาการต่ออายุของ Certbot จะทำงานโดยอัตโนมัติวันละ 2 ครั้ง แต่ไม่มีผู้ใช้งานคอยคัดลอกค่าใหม่ไปวาง ดังนั้นใบรับรองที่ออกด้วยวิธี manual จึงล้มเหลวในการต่ออายุและเกิดข้อผิดพลาดนี้:

Failed to renew certificate example.com with error: The manual plugin is not
working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with
--manual-auth-hook when using the manual plugin non-interactively.')

คุณสามารถแก้ไขปัญหานี้ได้โดยการเขียน script ด้วย --manual-auth-hook เพื่อเรียกใช้งาน API ของ DNS provider แต่ในกรณีนั้นคุณกำลังสร้าง DNS plugin ขึ้นมาใหม่ด้วยตนเอง ควรใช้ manual mode เพื่อเรียนรู้ขั้นตอนการทำงาน หรือใช้สำหรับกรณีพิเศษที่ต้องการทำเพียงครั้งเดียวสำหรับ domain ที่ยังไม่สามารถทำ automation สำหรับ DNS ได้ และควรตั้งการแจ้งเตือนไว้ล่วงหน้าก่อนครบกำหนด 90 วัน เนื่องจาก Let's Encrypt จะไม่ส่งอีเมลแจ้งวันหมดอายุอีกต่อไป สำหรับกรณีอื่นๆ ทั้งหมด ควรใช้ plugin แทน

วิธีการใช้ plugin: certbot-dns-cloudflare บน Ubuntu 24.04

DNS plugin จะใช้ API credential ของผู้ให้บริการ DNS เพื่อจัดการการสร้าง TXT record โดยอัตโนมัติ ทั้งในขั้นตอนการออกใบรับรอง (issuance) และทุกครั้งที่มีการต่ออายุ (renewal) ตัวอย่างนี้จะใช้ Cloudflare เนื่องจากเป็นผู้ให้บริการที่คนส่วนใหญ่ต้องการใช้งาน และมีแพ็กเกจติดตั้งใน Ubuntu

คู่มือ Certbot ของเราแนะนำให้ใช้แพ็กเกจ apt บน Ubuntu 24.04 ซึ่งรวมถึงกรณีของ Cloudflare ด้วย:

sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflare

ข้อควรระวังเรื่องเวอร์ชัน: ในคลังซอฟต์แวร์ของ 24.04 จะมาพร้อมกับ plugin เวอร์ชัน 2.0.0 และ Certbot เวอร์ชัน 2.9.0 โดย apt policy python3-certbot-dns-cloudflare คือเวอร์ชันที่คุณใช้งาน ความแตกต่างของเวอร์ชันนี้ไม่มีผลเสียต่อการทำงาน เนื่องจาก scoped API tokens สามารถใช้งานได้ เพราะ library python3-cloudflare ใน 24.04 เป็นเวอร์ชัน 2.11.1 ซึ่งสูงกว่าเวอร์ชัน 2.3.1 ที่ plugin ต้องการเพื่อรองรับ token สำหรับ Ubuntu เวอร์ชันเก่า library ดังกล่าวมีเวอร์ชันเก่าเกินไปสำหรับใช้งาน tokens ซึ่งเป็นสาเหตุของคำเตือนในอินเทอร์เน็ตที่ระบุว่า apt plugin บังคับให้ใช้ Global API Key แต่สำหรับ 24.04 ปัญหานี้ไม่เกิดขึ้นแล้ว

ในหน้า dashboard ของ Cloudflare ให้สร้าง scoped API token แทนการใช้ Global API Key: ไปที่ My Profile, เลือก API Tokens, จากนั้นเลือก Create Token โดยกำหนด permission เพียงอย่างเดียวคือ Zone / DNS / Edit และจำกัดสิทธิ์เฉพาะ zone ที่คุณต้องการออกใบรับรอง จากนั้นบันทึกข้อมูลลงในไฟล์ที่อนุญาตให้เฉพาะ root เท่านั้นที่อ่านได้:

sudo mkdir -p /root/.secrets
sudo tee /root/.secrets/cloudflare.ini > /dev/null <<'EOF'
dns_cloudflare_api_token = paste_your_scoped_token_here
EOF
sudo chmod 600 /root/.secrets/cloudflare.ini

Certbot จะตรวจสอบ permission ของไฟล์ และจะแจ้งเตือนเกี่ยวกับ Unsafe permissions on credentials configuration file หากไฟล์นั้นสามารถอ่านได้โดยผู้ใช้อื่น จากนั้นเริ่มดำเนินการออกใบรับรอง:

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d example.com -d '*.example.com'

Plugin จะสร้าง TXT records ผ่าน API, รอระยะเวลา propagation สั้นๆ, ดำเนินการตรวจสอบ (validation), และลบ records ทิ้ง หาก name servers ของ zone คุณอัปเดตการเปลี่ยนแปลงช้า ให้เพิ่มระยะเวลารอด้วย --dns-cloudflare-propagation-seconds 60 ใบรับรองจะถูกเก็บไว้ใน /etc/letsencrypt/live/example.com/ โดยคุณสามารถตั้งค่า nginx หรือ Apache ให้ชี้ไปยัง fullchain.pem และ privkey.pem ตามขั้นตอนในคู่มือพื้นฐาน รวมถึงการตั้งค่า deploy hook ด้วย

หากไม่พบ plugin ของผู้ให้บริการใน apt

archive ของเวอร์ชัน 24.04 มีการรวม package สำหรับ plugin ของผู้ให้บริการเพียงไม่กี่รายเท่านั้น เช่น Cloudflare, Route 53, DigitalOcean และ interface แบบ generic RFC 2136 ใช้คำสั่ง apt search certbot-dns เพื่อดูรายการทั้งหมด หากไม่พบผู้ให้บริการที่คุณใช้งานอยู่ ให้ปฏิบัติตามคำแนะนำนี้ซึ่งต่างจากแนวทางหลักของเรา: ให้ติดตั้ง Certbot และ plugin ผ่าน snap แทน และต้องลบ Certbot ที่ติดตั้งผ่าน apt ออกก่อน เพื่อป้องกันไม่ให้ renewal timer สองตัวทำงานซ้ำซ้อนกันบน /etc/letsencrypt:

sudo apt remove certbot python3-certbot-dns-cloudflare
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-yourprovider

snap plugin จะเชื่อมต่อกับ snap Certbot เท่านั้น และไม่สามารถใช้งานร่วมกับ apt version ได้ ดังนั้นจึงห้ามติดตั้งทั้งสองแบบไว้ในเครื่องเดียวกัน หากผู้ให้บริการ DNS ของคุณไม่มี API คุณมีทางเลือกคือการย้าย DNS ของโดเมนไปยังผู้ให้บริการที่มี API หรือติดตั้ง name server ของตนเองแล้วใช้งาน plugin rfc2136 ร่วมด้วย

การต่ออายุ: ทดสอบทันที ไม่ต้องรออีก 60 วัน

Certbot จะบันทึกข้อมูลการออกใบรับรองแต่ละใบไว้ใน /etc/letsencrypt/renewal/example.com.conf ซึ่งรวมถึง authenticator = dns-cloudflare และเส้นทางของ credentials เพื่อให้ timer ที่ทำงานวันละสองครั้งสามารถต่ออายุได้โดยอัตโนมัติโดยไม่ต้องดำเนินการใดๆ คุณควรทดสอบขั้นตอนทั้งหมดกับ staging environment:

sudo certbot renew --dry-run

หากผ่าน แสดงว่า credentials ใช้งานได้และกระบวนการ validation เสร็จสมบูรณ์ตั้งแต่ต้นจนจบ การต่ออายุจริงในอีก 60 วันข้างหน้าจะใช้ขั้นตอนเดียวกัน มีสองสิ่งที่ควรดำเนินการในวันนี้ ประการแรก ใบรับรองที่ต่ออายุแล้วบน disk จะไม่มีผลจนกว่า web server จะทำการ reload ดังนั้นควรตั้งค่า deploy hook ตามที่ระบุไว้ในคู่มือ nginx และ Apache ประการที่สอง ให้ระมัดระวังการใช้งานไฟล์ credentials เนื่องจากผู้ที่สามารถอ่านไฟล์นี้ได้จะสามารถแก้ไข DNS zone ของคุณ ซึ่งเพียงพอที่จะใช้ redirect mail หรือผ่านการตรวจสอบ DNS-01 challenges ของตนเองได้ ควรตั้งค่า permission เป็น mode 600 ภายใต้ /root จำกัดขอบเขตของ token ไว้เพียง zone เดียว และทำการ rotate หากคุณสงสัยว่าข้อมูลรั่วไหล

เมื่อคุณไม่จำเป็นต้องใช้ wildcard

Wildcard เป็นเครื่องมือที่เหมาะสมสำหรับ subdomain จำนวนมาก หรือ subdomain ที่ไม่สามารถคาดการณ์ได้ แต่ไม่ควรใช้เป็นค่าเริ่มต้นสำหรับกรณีอื่น

  • หากมีเพียงหนึ่ง subdomain หรือมีจำนวนน้อยที่ทราบแน่นอน: การใช้ใบรับรอง SAN (subject alternative name) แบบปกติจะง่ายกว่า certbot --nginx -d example.com -d www.example.com -d app.example.com รองรับได้สูงสุด 100 ชื่อผ่าน HTTP-01 และไม่ต้องเก็บข้อมูล DNS API credential ไว้บน server
  • Wildcard จะจับคู่กับ label เพียงหนึ่งเดียวเท่านั้น *.example.com ไม่ครอบคลุม example.com ซึ่งเป็นเหตุผลที่คำสั่งด้านบนต้องขอทั้งสองอย่าง และไม่ครอบคลุม a.b.example.com ด้วย ซึ่งกรณีนั้นจำเป็นต้องใช้ *.b.example.com
  • ทุก subdomain จะใช้ private key ชุดเดียวกัน หากเครื่องที่เก็บ key ถูกบุกรุก ทุกชื่อที่ wildcard ครอบคลุมจะได้รับผลกระทบพร้อมกันทั้งหมด
  • หาก Traefik ทำหน้าที่ terminate TLS (transport layer security) ให้กับ container ของคุณ คุณไม่จำเป็นต้องใช้ Certbot เลย: Traefik สามารถขอ wildcard certificates ได้เองผ่าน DNS-01 โดยใช้ provider token ประเภทเดียวกัน

กรณีที่ wildcard มีความจำเป็นอย่างยิ่ง: คือ subdomain ของลูกค้าแต่ละรายหรือแต่ละแอปพลิเคชันที่ถูกสร้างขึ้นเร็วกว่าความสามารถในการออกใบรับรองใหม่ และ host ภายในที่ไม่มีการเปิด port 80 ต่อสาธารณะ เช่น บริการที่เข้าถึงได้ผ่าน WireGuard VPN เท่านั้น เนื่องจาก DNS-01 ไม่มีการเชื่อมต่อกับ host ที่ขอใบรับรอง ดังนั้นแม้แต่เครื่องที่เป็นส่วนตัวโดยสมบูรณ์ก็สามารถถือครองใบรับรองที่ได้รับความเชื่อถือจากสาธารณะได้

FAQ

Certbot สามารถออก wildcard certificate ด้วย HTTP-01 ได้หรือไม่?

ไม่ได้ เนื่องจาก HTTP-01 ใช้เพื่อยืนยันความเป็นเจ้าของ hostname เพียงชื่อเดียว เพราะเซิร์ฟเวอร์ตรวจสอบจะดึงไฟล์ token จากชื่อนั้นโดยเฉพาะ Wildcard ครอบคลุมทุกชื่อภายใต้โดเมน ดังนั้น Let's Encrypt จึงกำหนดให้ใช้ DNS-01 challenge และ authenticator แบบ --nginx, --apache, --webroot และ --standalone ทั้งหมดทำงานผ่าน HTTP วิธีเดียวที่ใช้ได้คือการสร้าง TXT record ที่ _acme-challenge.example.com โดยการเพิ่มด้วยตนเองหรือใช้ DNS plugin

wildcard certificate ครอบคลุม root domain หรือไม่?

ไม่ Wildcard จะจับคู่กับ label เพียงหนึ่งชื่อเท่านั้น ดังนั้น *.example.com จะครอบคลุม www.example.com แต่ไม่ครอบคลุม example.com และไม่ครอบคลุม a.b.example.com หากต้องการขอทั้งสองชื่อใน certificate ใบเดียว ให้ใช้ -d example.com -d '*.example.com' ซึ่งจะสร้าง challenge ขึ้นมาสองรายการ และ TXT record ทั้งสองจะอยู่ที่ _acme-challenge.example.com เดียวกัน ดังนั้นควรเพิ่ม record ที่สองโดยไม่ลบ record แรกออก

ทำไม wildcard certificate ของฉันถึงไม่ต่ออายุโดยอัตโนมัติ?

เนื่องจาก certificate ถูกออกด้วย --manual การต่ออายุแต่ละครั้งจำเป็นต้องใช้ค่า TXT ใหม่ และระบบ unattended timer ไม่สามารถใส่ค่าดังกล่าวได้ การต่ออายุจึงหยุดลงพร้อมข้อผิดพลาด An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively ให้ทำการออก certificate ใหม่ด้วย DNS plugin เช่น certbot-dns-cloudflare หรือใช้สคริปต์ --manual-auth-hook และ --manual-cleanup-hook เพื่อแก้ไข record ผ่าน API ของผู้ให้บริการ

_acme-challenge TXT record ใช้เวลานานเท่าใดในการปรากฏขึ้น?

ขึ้นอยู่กับ DNS provider ของคุณ โดยใช้เวลาตั้งแต่ไม่กี่วินาทีไปจนถึงหลายนาที การตรวจสอบจะอ่านข้อมูลจาก authoritative servers ของ zone ของคุณ ดังนั้นควรตรวจสอบด้วย dig +short TXT _acme-challenge.example.com @1.1.1.1 และรอจนกว่าค่าที่คาดหวังจะปรากฏขึ้นก่อนดำเนินการแบบ manual ต่อไป หากใช้ plugin คุณสามารถเพิ่มเวลาการรอผ่านตัวเลือก propagation ของ plugin เช่น --dns-cloudflare-propagation-seconds 60 หากการตรวจสอบรายงานว่าไม่พบ record

wildcard certificate มีความปลอดภัยน้อยกว่า certificate ปกติหรือไม่?

การเข้ารหัส (cryptography) นั้นเหมือนกันทุกประการ ความแตกต่างอยู่ที่การปฏิบัติงาน เนื่องจาก private key ชุดเดียวครอบคลุมทุก subdomain หากถูกเจาะข้อมูลจะส่งผลกระทบเป็นวงกว้าง และข้อมูลรับรอง (credential) ของ DNS API ที่ระบบอัตโนมัติจำเป็นต้องใช้ถือเป็นข้อมูลลับที่สำคัญซึ่งถูกเก็บไว้บนเซิร์ฟเวอร์ หากคุณใช้งานเพียงไม่กี่ subdomain ที่ทราบแน่นอน การใช้ SAN certificate จะช่วยหลีกเลี่ยงปัญหาทั้งสองประการ ซึ่งเป็นเหตุผลที่คู่มือนี้แนะนำให้ข้ามการใช้ wildcard ไป