A Certbot DNS plugin needs a DNS provider token on the certificate host before it can create and remove _acme-challenge TXT records. Store that token as a root-owned credentials file instead of pasting it into shell history or a renewal file, because anyone who can read the token can use the provider API within the token's scope.
The example below uses the Cloudflare DNS plugin because it uses a small INI file and a provider-specific --dns-cloudflare-credentials flag. Other DNS plugins use their own key names and credential options, so keep the storage pattern but copy the exact credential entry from the provider plugin documentation.
When a certificate is later issued, Certbot records the credentials file path for renewal and reads the file again each time. A local file-mode check proves that the token is stored where only root can read it; a staging issuance proves that the token itself can update the provider's DNS zone.
Steps to store a DNS provider token for Certbot:
- Confirm the DNS plugin name and credential flag for the provider.
$ certbot plugins Saving debug log to /var/log/letsencrypt/letsencrypt.log ##### snipped ##### * dns-cloudflare Description: Obtain certificates using a DNS TXT record (if you are using Cloudflare for DNS). Interfaces: Authenticator, Plugin ##### snipped #####
Install and use the Certbot DNS plugin that matches the authoritative DNS provider for the zone. The credential file below is for Cloudflare; another provider may use a different file key or may use a service-account file instead of an API token.
- Create a root-only directory for DNS provider credentials.
$ sudo install -d -m 700 -o root -g root /etc/letsencrypt/secrets
Keeping provider tokens below /etc/letsencrypt/secrets keeps them near the Certbot configuration while separating them from public certificate material under /etc/letsencrypt/live.
- Create an empty Cloudflare credentials file with restrictive ownership and mode.
$ sudo install -m 600 -o root -g root /dev/null /etc/letsencrypt/secrets/cloudflare.ini
- Add the restricted DNS API token to the credentials file.
$ sudoedit /etc/letsencrypt/secrets/cloudflare.ini
# Cloudflare API token used by Certbot dns_cloudflare_api_token = <cloudflare-api-token>
Use a token scoped only to the DNS zone and record-edit permissions needed for certificate validation. Do not use a global account key unless the provider plugin has no safer token option.
- Confirm that only root can traverse the credentials directory and read the token file.
$ sudo stat -c '%a %U %G %n' /etc/letsencrypt/secrets /etc/letsencrypt/secrets/cloudflare.ini 700 root root /etc/letsencrypt/secrets 600 root root /etc/letsencrypt/secrets/cloudflare.ini
Certbot warns about unsafe permissions when a DNS credentials file can be accessed by other users. Fix that state with sudo chmod 600 /etc/letsencrypt/secrets/cloudflare.ini before issuing or renewing certificates.
- Use the stored credentials path when requesting or testing a DNS-validated certificate.
$ sudo certbot certonly \ --dns-cloudflare \ --dns-cloudflare-credentials /etc/letsencrypt/secrets/cloudflare.ini \ --dns-cloudflare-propagation-seconds 60 \ --dry-run \ --non-interactive \ --agree-tos \ --email admin@example.com \ -d example.com
After a successful issuance, Certbot saves the credentials file path in the renewal configuration. It does not copy the token contents into the renewal file, so the credentials file must remain in place and readable by root.
- Retest renewal after rotating the provider token or moving the credentials file.
$ sudo certbot renew --cert-name example.com --dry-run
A dry-run renewal is the practical check that the saved renewal configuration can still load the credentials path and complete DNS validation against the staging ACME service.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.