SSD Nodes Learn
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-07-23

Cách cấp wildcard certificate bằng DNS-01

Hướng dẫn dùng Certbot với DNS-01 challenge để cấp wildcard certificate. Cách dùng API thay vì làm thủ công để tự động hóa quá trình renewal hoàn toàn.

Tại sao wildcard certificate cần DNS-01

Một wildcard certificate bao phủ mọi subdomain cấp một của một domain: *.example.com khớp với app.example.com, blog.example.com, và bất kỳ tên nào khác chỉ sâu một label. Let's Encrypt chỉ cấp wildcard certificate thông qua DNS-01 challenge, vì vậy Certbot phải chứng minh quyền kiểm soát DNS của domain bằng cách publish một TXT record tại _acme-challenge.example.com. HTTP-01 challenge không thể đáp ứng, vì việc phục vụ một token file chỉ chứng minh quyền kiểm soát một hostname duy nhất, chính là hostname mà server validation đã fetch file đó. Một wildcard là một tuyên bố về mọi tên khả thi dưới domain, và bản ghi công khai duy nhất đại diện cho toàn bộ namespace chính là DNS.

Yêu cầu duy nhất đó quyết định mọi thứ khác trên trang này. Để vượt qua DNS-01, bạn phải có khả năng tạo các TXT record trong zone của domain, bằng cách làm thủ công hoặc thông qua API (application programming interface) của nhà cung cấp DNS. Cách làm thủ công chỉ dùng được một lần rồi sẽ thất bại khi renewal, vì một lý do cụ thể được nêu bên dưới. Cách dùng API, thông qua một Certbot DNS plugin, sẽ tự động renew mà không cần can thiệp, và đó là thiết lập bạn nên hướng tới.

Đây là chương về wildcard trong các hướng dẫn Certbot của chúng tôi. Các loại certificate single-hostname thông thường, cấu hình web server và các rule port 80 được đề cập trong Certbot với nginx trên Ubuntu 24.04Certbot với Apache trên Ubuntu 24.04.

Cách TXT record _acme-challenge hoạt động

Khi Certbot yêu cầu *.example.com, Let's Encrypt sẽ trả lời bằng một token ngẫu nhiên. Certbot kết hợp token đó với ACME (automatic certificate management environment) account key của bạn, hash kết quả bằng SHA-256, và tạo ra một giá trị văn bản ngắn. Giá trị đó phải xuất hiện dưới dạng một TXT record tại _acme-challenge.example.com. Let's Encrypt sau đó sẽ truy vấn các authoritative name servers của domain bạn từ hạ tầng của chính họ. Nếu bản ghi họ đọc được khớp với giá trị họ mong đợi, bạn đã chứng minh được quyền kiểm soát zone, và quyền kiểm soát zone được chấp nhận là quyền kiểm soát mọi tên dưới nó.

Hai chi tiết sau đây gây ra hầu hết các lỗi:

  • Yêu cầu example.com*.example.com trên cùng một certificate nghĩa là có hai challenge riêng biệt, và cả hai TXT record đều nằm tại cùng một tên, _acme-challenge.example.com. Cả hai phải tồn tại cùng một lúc. Việc thêm bản ghi thứ hai là đúng; nếu thay thế bản ghi thứ nhất bằng bản ghi thứ hai sẽ làm thất bại challenge thứ nhất.
  • Validation đọc các authoritative servers của bạn, nhưng các control panel của nhà cung cấp có thể mất một phút hoặc hơn để push một bản ghi mới đến đó. Hãy kiểm tra từ bên ngoài trước khi bạn chạy validation:
dig +short TXT _acme-challenge.example.com @1.1.1.1

Khi lệnh trên in ra giá trị mà Certbot đã yêu cầu, validation có thể thành công. Khi nó không in ra gì, hãy đợi và chạy lại.

Thử nghiệm một lần: chế độ manual

Chế độ manual yêu cầu bạn tự thực hiện chỉnh sửa DNS, đây là cách tốt nhất để hiểu cơ chế trước khi bạn tự động hóa nó:

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

Dấu ngoặc kép quanh wildcard giúp shell không xử lý * như một pattern filename. Certbot sẽ tạm dừng với các hướng dẫn:

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

Hãy tạo TXT record đó trong panel của nhà cung cấp DNS, xác nhận nó đã hiển thị bằng lệnh dig ở trên, và chỉ sau đó mới nhấn Enter. Vì lần chạy này yêu cầu cả bare domain và wildcard, Certbot sẽ prompt hai lần; hãy giữ cả hai bản ghi cho đến khi quá trình issuance hoàn tất. Thành công sẽ kết thúc với các dòng quen thuộc:

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

Tại sao chế độ manual không thể tự renew

Mỗi lần renewal là một challenge mới với một token mới, vì vậy giá trị TXT sẽ thay đổi mỗi lần. Bản ghi bạn dán hôm nay sẽ vô dụng sau 60 ngày. Timer renewal sẽ chạy Certbot tự động hai lần một ngày, và không có ai ngồi trước bàn phím để dán giá trị mới, nên một certificate được cấp thủ công sẽ thất bại khi renewal với lỗi chính xác này:

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.')

Bạn có thể đáp ứng yêu cầu đó bằng cách viết các script --manual-auth-hook gọi API của nhà cung cấp DNS, nhưng khi đó bạn đang tự xây dựng một DNS plugin bằng tay. Hãy dùng chế độ manual để học luồng hoạt động, hoặc dùng cho một trường hợp duy nhất trên một domain mà bạn chưa thể tự động hóa DNS, và hãy đặt nhắc nhở trước ngày thứ 90, vì Let's Encrypt không còn gửi email thông báo hết hạn nữa. Với mọi thứ khác, hãy dùng plugin.

Cách dùng plugin: certbot-dns-cloudflare trên Ubuntu 24.04

Một DNS plugin giữ thông tin xác thực API cho nhà cung cấp DNS của bạn và tự thực hiện toàn bộ quy trình TXT record, tại thời điểm issuance và tại mỗi lần renewal. Cloudflare là ví dụ thực tế ở đây vì đây là plugin nhà cung cấp mà hầu hết mọi người cần, và nó đã có sẵn trong gói Ubuntu.

Các hướng dẫn Certbot của chúng tôi khuyến nghị dùng các package apt trên Ubuntu 24.04, và quan điểm này cũng áp dụng cho Cloudflare:

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

Một lưu ý nhỏ về phiên bản. Kho lưu trữ 24.04 đi kèm plugin này ở phiên bản 2.0.0 cùng với Certbot 2.9.0; apt policy python3-certbot-dns-cloudflare hiển thị phiên bản của bạn. Sự lệch phiên bản này không gây hại, và các scoped API tokens vẫn hoạt động, vì thư viện python3-cloudflare cơ sở trong 24.04 là 2.11.1, cao hơn mức 2.3.1 mà plugin cần để hỗ trợ token. Trên các bản Ubuntu cũ hơn, thư viện đó quá cũ để hỗ trợ token, đó là lý do tại sao bạn có thể thấy các cảnh báo trực tuyến về việc plugin apt bắt buộc phải dùng Global API Key. Trên 24.04, những cảnh báo đó không còn áp dụng.

Trong dashboard Cloudflare, hãy tạo một scoped API token, đừng dùng Global API Key: My Profile, sau đó là API Tokens, rồi Create Token, với quyền duy nhất là Zone / DNS / Edit, giới hạn cho đúng một zone mà bạn đang cấp phát. Hãy lưu nó vào một file mà chỉ root mới có quyền đọc:

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 sẽ kiểm tra chế độ và cảnh báo về Unsafe permissions on credentials configuration file nếu file có thể bị đọc bởi người khác. Bây giờ hãy thực hiện issuance:

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

Plugin sẽ tạo các TXT record thông qua API, đợi một khoảng thời gian propagation ngắn, cho phép validation chạy, sau đó xóa các bản ghi đó đi. Nếu các authoritative name servers của zone bạn phản hồi chậm với các thay đổi, hãy tăng thời gian chờ bằng --dns-cloudflare-propagation-seconds 60. Certificate sẽ nằm trong /etc/letsencrypt/live/example.com/, và bạn trỏ nginx hoặc Apache vào fullchain.pemprivkey.pem chính xác như các hướng dẫn cơ bản đã chỉ, bao gồm cả deploy hook.

Nếu plugin của nhà cung cấp không có trong apt

Kho lưu trữ 24.04 chỉ đóng gói plugin cho một số ít nhà cung cấp, trong đó có Cloudflare, Route 53, DigitalOcean và interface RFC 2136 chung. Chạy apt search certbot-dns để xem danh sách. Nếu nhà cung cấp của bạn không có trong danh sách, đây là trường hợp duy nhất mà lời khuyên "ưu tiên apt" của chúng tôi thay đổi: hãy cài đặt Certbot và plugin từ snap, và hãy gỡ bỏ Certbot từ apt trước để hai timer renewal không bao giờ tranh chấp /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

Một snap plugin chỉ kết nối với snap Certbot; nó không thể mở rộng cho bản apt, đó là lý do tại sao hai bản cài đặt không được tồn tại song song. Và nếu host DNS của bạn không cung cấp API, các lựa chọn thực tế của bạn là chuyển DNS của domain sang một nhà cung cấp có API, hoặc tự chạy name server riêng và trỏ plugin rfc2136 vào đó.

Renewal: hãy chứng minh ngay bây giờ, không phải sau 60 ngày

Certbot ghi lại cách mỗi certificate được cấp trong /etc/letsencrypt/renewal/example.com.conf, bao gồm cả authenticator = dns-cloudflare và đường dẫn credentials, vì vậy timer tiêu chuẩn chạy hai lần mỗi ngày sẽ tự động renew mà không cần bạn giúp. Hãy thử nghiệm toàn bộ quy trình với môi trường staging:

sudo certbot renew --dry-run

Nếu thành công nghĩa là thông tin xác thực hoạt động và validation hoàn tất từ đầu đến cuối; quá trình renewal thật sự sau 60 ngày sẽ đi theo cùng một lộ trình. Có hai việc bạn nên làm ngay hôm nay. Thứ nhất, một certificate đã được renew trên disk sẽ không thay đổi gì cho đến khi web server reload nó, vì vậy hãy thiết lập deploy hook như đã mô tả trong hướng dẫn nginx và Apache. Thứ hai, hãy bảo mật file credentials: bất kỳ ai có thể đọc nó đều có thể chỉnh sửa DNS zone của bạn, điều này đủ để chuyển hướng mail hoặc thực hiện các DNS-01 challenge của riêng họ. Hãy giữ nó ở mode 600 dưới /root, giới hạn token trong một zone, và hãy rotate nó nếu bạn nghi ngờ bị lộ.

Khi nào bạn không cần wildcard

Wildcard là công cụ phù hợp cho nhiều subdomain, hoặc cho các subdomain mà bạn không thể dự đoán trước. Nó là lựa chọn sai lầm mặc định cho mọi thứ khác.

  • Một subdomain, hoặc một vài subdomain đã biết trước: một certificate SAN (subject alternative name) thông thường sẽ đơn giản hơn. certbot --nginx -d example.com -d www.example.com -d app.example.com bao phủ lên đến 100 tên thông qua HTTP-01 thuần túy, và không có API credential DNS nào phải lưu trên server.
  • Một wildcard chỉ khớp chính xác một label. *.example.com không bao phủ bare example.com, đó là lý do tại sao các lệnh ở trên yêu cầu cả hai, và nó cũng không bao phủ a.b.example.com; việc đó sẽ cần *.b.example.com.
  • Một private key đứng sau mọi subdomain. Nếu máy chủ giữ key đó bị xâm nhập, mọi tên mà wildcard bao phủ sẽ bị ảnh hưởng cùng một lúc.
  • Nếu Traefik xử lý TLS (transport layer security) cho các container của bạn, bạn hoàn toàn không cần Certbot: Traeft tự yêu cầu wildcard certificate qua DNS-01, sử dụng cùng loại provider token tương tự.

Nơi wildcard thực sự phát huy tác dụng: các subdomain theo từng khách hàng hoặc từng ứng dụng được tạo ra nhanh hơn mức bạn muốn cấp lại certificate, và các host nội bộ không có port 80 công khai, chẳng hạn như các dịch vụ chỉ có thể truy cập qua một WireGuard VPN. DNS-01 không bao giờ kết nối tới host đang được chứng thực, vì vậy ngay cả một máy chủ hoàn toàn riêng tư cũng có thể giữ một certificate được tin cậy công khai.

FAQ

Certbot có thể cấp wildcard certificate bằng HTTP-01 không?

Không. HTTP-01 chứng minh quyền kiểm soát một hostname, vì server validation sẽ fetch một token file từ chính tên đó. Một wildcard bao phủ mọi tên dưới domain, vì vậy Let's Encrypt yêu cầu DNS-01 challenge cho nó, và các authenticator --nginx, --apache, --webroot--standalone đều dựa trên HTTP. Cách duy nhất là một TXT record tại _acme-challenge.example.com, được đặt thủ công hoặc bằng một DNS plugin.

Một wildcard certificate có bao phủ root domain không?

Không. Wildcard chỉ khớp chính xác một label, vì vậy *.example.com bao phủ www.example.com nhưng không bao phủ bare example.com, và cũng không bao phủ a.b.example.com. Hãy yêu cầu cả hai tên trên một certificate bằng -d example.com -d '*.example.com'. Việc này tạo ra hai challenge, và cả hai TXT record đều nằm tại cùng một tên _acme-challenge.example.com, vì vậy hãy thêm bản ghi thứ hai mà không xóa bản ghi thứ nhất.

Tại sao wildcard certificate của tôi không tự động renew?

Vì nó được cấp bằng --manual. Mỗi lần renewal cần một giá trị TXT hoàn toàn mới, và timer tự động không có cách nào để dán nó vào, nên quá trình renewal sẽ dừng lại với lỗi An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively. Hãy cấp lại certificate bằng một DNS plugin như certbot-dns-cloudflare, hoặc cung cấp các script --manual-auth-hook--manual-cleanup-hook để chỉnh sửa bản ghi thông qua API của nhà cung cấp.

Một TXT record _acme-challenge mất bao lâu để xuất hiện?

Tùy thuộc vào nhà cung cấp DNS của bạn: từ vài giây đến vài phút. Validation đọc các authoritative servers của zone bạn, vì vậy hãy kiểm tra bằng dig +short TXT _acme-challenge.example.com @1.1.1.1 và đợi cho đến khi giá trị mong đợi xuất hiện trước khi tiếp tục chạy thủ công. Với plugin, hãy tăng thời gian chờ tích hợp sẵn thông qua tùy chọn propagation của plugin, ví dụ --dns-cloudflare-propagation-seconds 60, nếu validation báo rằng không tìm thấy bản ghi.

Một wildcard certificate có kém an toàn hơn một certificate thông thường không?

Mật mã học là như nhau. Sự khác biệt nằm ở vận hành: một private key bao phủ mọi subdomain, vì vậy một sự xâm nhập sẽ ảnh hưởng trên phạm vi rộng hơn, và thông tin xác thực DNS API mà quá trình tự động hóa yêu cầu chính là một bí mật nhạy cảm được lưu trữ trên server. Nếu bạn chỉ chạy một vài subdomain đã biết, một certificate SAN sẽ tránh được cả hai vấn đề này, đó chính là lý do tại sao hướng dẫn này khuyên bạn nên bỏ qua wildcard.