
I read your Let’s Encrypt TLS/SSL certificate acme.sh tutorial. But, I need to set up and use Cloudflare DNS with acme.sh. How do I secure my Nginx web server with Let’s Encrypt TLS/SSL certificate issue with Cloudflare DNS?
For wildcard TLS/SSL certificates, the only challenge method Let’s Encrypt accepts is the DNS challenge to authenticate the domain ownership. Therefore, we need to Cloudflare DNS API to add/modify DNS for our domain. This tutorial explains how to generate a wildcard TLS/SSL certificate using Let’s Encrypt client called acme.sh running on Linux or Unix-like systems.
| Tutorial requirements | |
|---|---|
| Operating system/app | Linux or Unix with Nginx and Cloudflare API key |
| Root privileges required | Yes |
| Difficulty | Intermediate (rss) |
| Estimated completion time | 10m |
Prerequisite to get Let’s Encrypt wildcard certificate
You need the Nginx server installed and running. For example:$ sudo apt install nginx
$ sudo yum install nginx
See the following tutorials:
Step 1 – Getting Cloudflare API key
Head over to Cloudflare control panel and obtain API key:
Click on the “Create Token” > “Edit zone DNS” > Use template :
Make sure you set up DNS Permissions to Edit and include zone to your DNS domain name such as cyberciti.biz:
Finally click on the “Continue to summary” to see your “Edit zone DNS API token summary” as follows:
Finally, copy token displayed on the screen to access the Cloudflare API. Do not share this token with anyone. Keep it secure and secret.
Step 2 – Installing acme.sh client
After getting Cloudflare DNS API key, now set up the acme.sh client. Hence, clone the acme.sh repo using the git command:$ cd /tmp/
$ git clone https://github.com/Neilpang/acme.sh.git
Install the client but first log in as root user using the su command/sudo command:$ sudo -i
# touch /root/.bashrc
# cd /tmp/acme.sh/
# acme.sh --install --accountemail your-email-id@domain-here

Step 3 – Issuing Let’s Encrypt wildcard certificate
So far we set up Nginx, obtained Cloudflare DNS API key, and now it is time to use acme.sh to get a wildcard certificate for cyberciti.biz domain. First set up the CF_Token using export command as follows:# Export single variable for the CloudFlare DNS challenge to work #
# export CF_Token="Your_Cloudflare_DNS_API_Key_Goes_here"
No need to define shell variable CF_Account_ID and CF_Zone_ID as those will be automatically pulled by the acme.sh. Then request the certificate. Make sure you replace cyberciti.biz with your domain name:# acme.sh --issue --dns dns_cf --ocsp-must-staple --keylength 4096 -d cyberciti.biz -d *.cyberciti.biz
If you prefer Elliptic-curve cryptography (ECC/ECDSA) instead of RSA, try:
Although it is possible to configure Nginx to use RSA and ECDSA certificates, I will use RSA here as my LB only supports RSA. But you can serve a dual-cert config too which offers an RSA certificate by default, and a (much smaller) ECDSA certificate to those clients that indicate support.
# acme.sh --issue --dns dns_cf --ocsp-must-staple --keylength ec-384 -d cyberciti.biz -d *.cyberciti.biz
[Tue 21 Jul 2020 09:41:22 AM UTC] Creating domain key [Tue 21 Jul 2020 09:41:22 AM UTC] The domain key is here: /root/.acme.sh/cyberciti.biz_ecc/cyberciti.biz.key [Tue 21 Jul 2020 09:41:22 AM UTC] Multi domain='DNS:cyberciti.biz,DNS:*.cyberciti.biz' [Tue 21 Jul 2020 09:41:22 AM UTC] Getting domain auth token for each domain [Tue 21 Jul 2020 09:41:23 AM UTC] Getting webroot for domain='cyberciti.biz' [Tue 21 Jul 2020 09:41:23 AM UTC] Getting webroot for domain='*.cyberciti.biz' [Tue 21 Jul 2020 09:41:23 AM UTC] cyberciti.biz is already verified, skip dns-01. [Tue 21 Jul 2020 09:41:23 AM UTC] *.cyberciti.biz is already verified, skip dns-01. [Tue 21 Jul 2020 09:41:23 AM UTC] Verify finished, start to sign. [Tue 21 Jul 2020 09:41:23 AM UTC] Lets finalize the order, Le_OrderFinalize: https://acme-v02.api.letsencrypt.org/acme/finalize/91904709/4305779370 [Tue 21 Jul 2020 09:41:24 AM UTC] Download cert, Le_LinkCert: https://acme-v02.api.letsencrypt.org/acme/cert/0436c4ebf2a5784d099b29e0debb715b9b21 [Tue 21 Jul 2020 09:41:24 AM UTC] Cert success. -----BEGIN CERTIFICATE----- MIIEyDCCA7CgAwIBAgISBDbE6/KleE0Jmyng3rtxW5shMA0GCSqGSIb3DQEBCwUA MDEwMTkwODQxMjNaMBgxFjAUBgNVBAMTDWN5YmVyY2l0aS5iaXowdjAQBgcqhkjO PQIBBgUrgQQAIgNiAATgsEKKKKZQBxND706ETdaZUwapb8439jksX4P4eJldG03A ..... .. RuA8fFmhcftOGL2FZmQibR0m2ReMiAAf4m4dmU4uJ1UNp6AabA6Fj+BTbaLRFQqJ SFGM3REOsgJxWt4ee+oDwZXkpDwUHNqiA7ldyw== -----END CERTIFICATE----- [Tue 21 Jul 2020 09:41:24 AM UTC] Your cert is in /root/.acme.sh/cyberciti.biz_ecc/cyberciti.biz.cer [Tue 21 Jul 2020 09:41:24 AM UTC] Your cert key is in /root/.acme.sh/cyberciti.biz_ecc/cyberciti.biz.key [Tue 21 Jul 2020 09:41:24 AM UTC] The intermediate CA cert is in /root/.acme.sh/cyberciti.biz_ecc/ca.cer [Tue 21 Jul 2020 09:41:24 AM UTC] And the full chain certs is there: /root/.acme.sh/cyberciti.biz_ecc/fullchain.cer |
Your Cloudflare DNS API key is sotred in /root/.acme.sh/account.conf file and we can see it using the cat command or grep command:# cat /root/.acme.sh/account.conf
# grep '_CF_' /root/.acme.sh/account.conf
Step 4 – Configuring Nginx web server
Make sure you create a Diffie-Hellman key exchange file as follows using the openssl command:# mkdir -pv /etc/nginx/letsencrypt/cyberciti.biz/
# cd /etc/nginx/letsencrypt/cyberciti.biz/
# openssl dhparam -out /etc/nginx/ssl/letsencrypt/cyberciti.biz/dhparams.pem -dsaparam 4096
Then edit your Nginx config file:# vi /etc/nginx/nginx.conf
Edit/update as follows:
# Port 80 config server { listen 80 default_server; # IPv4 listen [::]:80 default_server; # IPv6 server_name www.cyberciti.biz; access_log off; error_log off; root /var/www/html; return 301 https://$host$request_uri; } # Port 443 config server { listen 443 ssl http2; # IPv4 listen [::]:443 ssl http2; # HTTP/2 TLS IPv6 server_name www.cyberciti.biz; # domain name # Set document root location / { root /var/www/html; index index.html; } # Set access and error log for this vhos access_log /var/log/nginx/cyberciti.biz_access.log; error_log /var/log/nginx/cyberciti.biz_error.log; # TLS/SSL CONFIG ssl_certificate /etc/nginx/ssl/cyberciti.biz/cyberciti.biz.fullchain.cer; ssl_certificate_key /etc/nginx/ssl/cyberciti.biz/cyberciti.biz.key; # ECC/ECDSA certificates (dual config) #ssl_certificate /etc/nginx/ssl/cyberciti.biz/cyberciti.biz.fullchain.cer.ecc; #ssl_certificate_key /etc/nginx/ssl/cyberciti.biz/cyberciti.biz.key.ecc; ssl_dhparam /etc/nginx/ssl/cyberciti.biz/dhparams.pem; # A little bit of optimization ssl_session_timeout 1d; ssl_session_cache shared:NixCraftSSL:10m; # TLS version 1.2 and 1.3 only ssl_session_tickets off; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; # HSTS (ngx_http_headers_module is required) # ************************************************************************* # WARNING - Wrong headers can create problems. Read docs otherwise # all 3rd party scripts/ads won't load and in some case # browser won't work. Read docs @ https://developer.mozilla.org # ************************************************************************* add_header Strict-Transport-Security "max-age=63072000" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Xss-Protection "1; mode=block" always; add_header Referrer-Policy strict-origin-when-cross-origin always; add_header Feature-policy "accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'" always; # *************************************************************************************************** # WARNING: The HTTP Content-Security-Policy response header allows sysadmin/developers # to control resources the user agent is allowed to load for a given page. # Wrong config can create problems for third party scripts/ad networks. Hence read the following url: # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy # **************************************************************************************************** add_header content-security-policy "default-src https://www.cyberciti.biz:443" always; # OCSP stapling # Verify chain of trust of OCSP response using Root CA and Intermediate certs ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/nginx/ssl/cyberciti.biz/cyberciti.biz.fullchain.cer; # Replace with the IP address of your resolver resolver 1.1.1.1; } |
Step 5 – Installing Let’s Encrypt wildcard certificate
Install your certificate (replace the systemct reload nginx command as per your Linux/Unix distro)::# DOMAIN="cyberciti.biz"
# CONFIG_ROOT="/etc/nginx/ssl/cyberciti.biz"
# acme.sh -d "$DOMAIN"
--install-cert
--reloadcmd "systemctl reload nginx"
--fullchain-file "${CONFIG_ROOT}/$DOM.fullchain.cer"
--key-file "${CONFIG_ROOT}/$DOM.key"
--cert-file "${CONFIG_ROOT}/$DOM.cer"
Install ECC/ECDSA if you need them too (again, replace the systemct reload nginx command as per your Linux/Unix distro):# acme.sh -d "$DOMAIN"
--ecc
--install-cert
--reloadcmd "systemct reload nginx"
--fullchain-file "${CONFIG_ROOT}/$DOM.fullchain.cer.ecc"
--key-file "${CONFIG_ROOT}/$DOM.key.ecc"
--cert-file "${CONFIG_ROOT}/$DOM.cer.ecc"
Step 6 – Testing
Make sure you open Nginx server tcp port # 443 if not already opened. For example, here is how we can open it on Ubuntu or Debian Linux:$ sudo ufw allow https comment 'Open all to access Nginx port 443'
Fire a web browser and type the url:https://www.cyberciti.biz/
Of coruse we can visit $ testssl.sh --fast --parallel https://www.cyberciti.biz/
Conclusion
You created a wildcard TLS/SSL certificate for your domain using acme.sh and Cloudflare DNS API for domain verification. Please note that acme.sh automatically configure a