In this howto I’m going to talk about setup free SSL with Let’s Encrypt and DNS challenge validation on a Linux server, with auto-renew support. The free SSL certificates will work for both Nginx and Apache, the two most popular open source web servers.
Why use DNS challenge validation instead of web server validation
There are many articles on the Internet describing how to setup free SSL by using Let’s Encrypt. However most of them use web server challenge validation. This is great, though sometimes your web server setup don’t allow you to do that easily. There are several possible reasons to use DNS instead.
- You have more than one web servers to serve your site, load balanced for example. You can’t tell in advance which server will respond to the challenges from Let’s Encrypt servers. There are solution for this situation but it is not trivial to setup.
- Your web site runs in a intranet and no public access, thus unable to perform a web challenge validation.
- You host quite a lot domains on your web server, you might want to avoid touching web server configurations to lower risks.
- You have complex setup in your web server, such as all kinds of redirection between domains(non-www to www or vice versa, which is very common), mixed dynamic and static content, reverse caching proxies, firewalls etc., sometimes it might be hard to set it up quickly and correctly for web challenge validation.
- You web server is managed by some other administrator and you don’t want to bother him.
- You are building a new site and the web server is not up yet.
- You want to keep another possible method on hand just in case.
Your domain must be using one of the DNS providers that provide API access and is supported by the Lexicon DNS record manipulating tool. Check here for the full and up-to-date list of supported DNS service providers. Some commonly used DNS providers are in the list, such as AWS Route53, Cloudflare, Digital Ocean, EasyDNS, Namesilo, NS1, Rage4, Vultr.
If you are already using one of these providers to serve your domain, just move on. If you are not, I recommend you to try Cloudflare if possible. I’ll use Cloudflare as example in this howto.
Gather necessary information
First you need to log into your DNS providers’s website and get the required API access information. Take Cloudflare for example, after you logged in, click your email address at the top right corner of the page, then choose “My Settings” from the menu. This will open your account profile. Scroll down and you will see a section for API information, just like below.
Click the “View API Key” button for Global API key, you will then see a popup text box with you key in it. We will need this key later. For different DNS providers, they may provide the API key in different but similar name, such as API token.
Install required software
This howto will use CentOS for example to demonstrate how to install necessary software packages. If you are using a different Linux distribution such as Ubuntu / Arch / Gentoo, the command line and package name might be a bit different. Leave a reply below if you don’t know how to find that out, I’m glad to help.
First install OpenSSL Git, Python, Pip.
yum install openssl git python python-pip
Then create a directory to hold the software we need to install from GitHub.
Install Dehydrated, which is the tool to manage Let’s Encrypt SSL certificate. It can register, apply and renew certs for you.
git clone https://github.com/lukas2511/dehydrated.git /usr/local/repo/dehydrated
Then install Lexicon, a Python package that talks to DNS providers and manges DNS records. Dehydrated will use it to create DNS challenge validation record for Let’s Encryption.
pip install dns-lexicon git clone https://github.com/AnalogJ/lexicon.git /usr/local/repo/lexicon
If you are using DNS provider other than Cloudflare demonstrated here, you may need to install extra dependencies for Lexicon, check for details here.
Now you need to configure Dehydrated to tell it necessary information about the SSL certificate you would like to request. Create a new text file
/etc/dehydrated/config and put below content in:
CHALLENGETYPE=dns-01 CONTACT_EMAIL=your_email_address HOOK=/usr/local/repo/lexicon/examples/dehydrated.default.sh
Remember to put in your own email address for the second line. This configuration tells Dehydrated to use DNS challenge instead of the default web server challenge.
Then create file
/etc/dehydrated/domains.txt to put in the domain name you would like to apply SSL certificate for. For example, if you have a domain example.com, and would like the certificate to work for hosts including www.example.com, forum.example.com, blog.example.com, then put a line as below in the file.
example.com www.example.com forum.example.com blog.example.com
Apply for Let’s Encrypt SSL certificate
Now you are ready to apply for the Let’s Encrypt SSL certificate for your domain. First is to register on Let’s Encrypt using the email address you provided earlier in the configuration.
/usr/local/repo/dehydrated/dehydrated --register --accept-terms
Then run below commands to apply for a new certificate
export LEXICON_CLOUDFLARE_USERNAME=your_cloudflare_account_email export LEXICON_CLOUDFLARE_TOKEN=your_cloudflare_api_key export PROVIDER=cloudflare /usr/local/repo/dehydrated/dehydrated
This tells the dehydrated script to read the DNS configuration information from the environment variables. We do this just for quick setup. Later we will put them in a script for easier execution.
Once you started these commands, you will see output saying that Dehydrated is trying to request for certificate, setup DNS record etc. Once it’s finished, your certificate will be located under
These commands are for Cloudflare. If you are using a different DNS provider, consult this link for corresponding parameters.
Setup web server
Now it’s time to tell your web server to use the certificates for your site. I’m using Nginx so below are the instruction for Nginx. If you need Apache information, please leave a message below and I’m glad to help.
Put below content in your Nginx configuration file. They can be in the http block if you only host example.com, or can be put in the server block for example.com if you host multiple different domains.
# Below 3 lines enhance SSL security ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; ssl_prefer_server_ciphers on; ssl_dhparam /etc/nginx/dhparam.pem; # Change the file name in below two lines to your actual certificate names. ssl_certificate /etc/dehydrated/certs/example.com/fullchain.pem; ssl_certificate_key /etc/dehydrated/certs/example.com/privkey.pem; ssl_session_cache shared:SSL:50m; ssl_session_timeout 10m;
Make sure you change the two lines that refer to the certificate files to your actual file.
Then run below command to generate the dhparam file as referenced in above configuration. It may take a while depends on the hardware configuration of your server.
# openssl dhparam -out /etc/nginx/dhparam.pem 2048
After it is done, you can now run
nginx -t to test your Nginx configuration. Make sure you see it says everything is OK before move on! A wrong configuration may take your site offline.
Now go to https://your.site.address, you will see your site loaded via HTTPS if you have done every step correctly.
Setup cron job for auto renewal
The Let’s Encrypt SSL certificate is free and easy to get, but it is only validate for 90 days. So you need to setup an scheduled job(called cron job on Linux) to check the remaining time of your certificates and renew it if necessary.
To do that, first create a script with below content, and save it as /usr/local/sbin/letsencrypt.sh
#!/bin/bash export LEXICON_CLOUDFLARE_USERNAME=your_cloudflare_account_email export LEXICON_CLOUDFLARE_TOKEN=your_cloudflare_api_key export PROVIDER=cloudflare /usr/local/repo/dehydrated/dehydrated --cron nginx -s reload
Again, remember to put correct DNS parameters as your actual situation. And remind that the dehydrated command has a “–cron” option. This option takes care of necessary certificate expiration check and renew process. The last command reloads Nginx so if the cerificates are renewed nginx will pick them up.
Then make the script executable and scheduled to run every week.
chmod +x /usr/local/sbin/letsencrypt.sh ln -s /usr/local/sbin/letsencrypt.sh /etc/cron.weekly/letsencrypt.sh
Now you have finished setup of Let’s Encrypt free SSL certificate, you site now serves content via the much safer HTTPS protocol, and you have auto renew in place. Enjoy it.