Have you ever wondered if it was possible to obtain an Server Certificate
before you migrate a website? I always assumed the DNS
had to be switched before the certificate validation
could take place. I've come to find there are more options available.
The Scenario
My company is currently in the process of moving all of our client production sites to a new server. Part of that effort is ensuring all sites be placed on https
.
Server Certificate Challenges
Let's Encrypt offers domain-validated certificates, meaning they have to check that the certificate request comes from a person who actually controls the domain. They do this by sending the client a unique token, and then making a web or DNS request to retrieve a key derived from that token.
There are two main options to obtain a server certificate
:
-
HTTP Challenge
- Posting a specifiedfile
in a specified location on a web site -
DNS Challenge
- Posting a specifiedDNS record
in the domain name system
HTTP Challenge
This is usually handled by adding a token
inside a .well-known
directory in your web root
. Certbot
can then confirm you actually control resources on the specified domain, and will sign a certificate
.
DNS Challenge
This approach requires you to add specific DNS TXT
entry for each domain requested. This is useful when you haven't switched DNS
yet, but want to issue a certificate
in anticipation (for testing).
For more information on challenges, visit certbot's documentation.
Setup
We'll be discussing the DNS Challenge
approach for the rest of the article.
In the examples below, I'll be using Apache
& Ubuntu 16.04
following this guide. To find documentation for your specific web server / operating system, go to certbot's homepage.
First we need to install certbot
along with all necessary dependencies.
# run as root
apt-get update \
&& apt-get install software-properties-common \
&& add-apt-repository -y universe \
&& add-apt-repository -y ppa:certbot/certbot \
&& apt-get update \
&& apt-get install -y python-certbot-apache
Configuration
I won't be going over wildcard domains here, but they are an option. Refer to their documentation.
We now need to tell certbot
which domains we would like to issue a certificate
for. Remember to add each subdomain individually.
Since we may have multiple vhosts
per server, we decided to use the --manual
& certonly
flags.
# run as root
# replace with your domain
# add all relevant subdomains
certbot --manual --preferred-challenges dns certonly \
-d yourwebsite.com \
-d www.yourwebsite.com \ # don't forget www binding
-d staging.yourwebsite.com \ # example subdomain
-d staging.stage1.yourwebsite.com # example long subdomain
Challenge Prompts
Once you run the command above, it will prompt you to add a DNS TXT
record for each specified domain. It will look like this:
Please deploy a DNS TXT record under the name
_acme-challenge.yourwebsite.com with the following value:
[random-string-of-characters]
Before continuing, verify the record is deployed.
(This must be set up in addition to the previous challenges; do not remove,
replace, or undo the previous challenge tasks yet. Note that you might be
asked to create multiple distinct TXT records with the same name. This is
permitted by DNS standards.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Now here's the important part. You need to remove the base url
from each record name
, like so:
requested name from certbot | actual name to add in DNS
|
---|---|
_acme-challenge.yourwebsite.com |
_acme-challenge |
_acme-challenge.www.yourwebsite.com |
_acme-challenge.www |
_acme-challenge.staging.yourwebsite.com |
_acme-challenge.staging |
_acme-challenge.staging.stage1.yourwebsite.com |
_acme-challenge.staging.stage1 |
Once you add the DNS TXT
records, and click Continue
through each challenge prompt respectively, the validation should pass.
Press Enter to Continue
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/yourwebsite.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/yourwebsite.com/privkey.pem
Your cert will expire on 2019-04-24. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
Updating Your VHost
Now that we have a valid certificate, we can update our vhost
:
# inside the 443 binding
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/yourwebsite.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/yourwebsite.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/yourwebsite.com/chain.pem
Then restart Apache
:
sudo apachectl configtest
# if syntax ok
sudo apachectl restart
Bonus: Setup Auto Renewal
We'll leverage the crontab
of the root
user to automatically renew certificates that will expire soon.
# run as root
# edit the crontab
crontab -e
Then add the following two lines at the bottom:
# every Monday at 2:30am
30 2 * * 1 /usr/bin/certbot renew --deploy-hook "service apache2 reload" >> /var/log/letsencrypt/le-renew.log
The certbot
will try and renew any certificates marked for renewal once a week. We then use the --deploy-hook
to only reload apache
if necessary.
Special thanks to Daniel McCarney for the updated crontab
code.
Top comments (6)
Hi Michael,
Great post! I can suggest one small improvement if you're interested :-)
Instead of unconditionally restarting
apache2
weekly you could do two things:service apache2 reload
instead ofrestart
will reduce your downtime but still let Apache pick up certificates that have changed on disk.--deploy-hook
feature of the renew command.Adding
--deploy-hook "service apache2 reload"
to your Certbotrenew
crontab will ensure Apache2 is gracefully reloaded only when a certificate is actually renewed.Hope that helps!
Thanks for the suggestion, I didn't know about that flag. That definitely seems like the way to go.
I updated the post with your code example.
I assume that in your scenario, the
certbot renew
is running on those web hosts after they've already gone live?Just asking because I noticed in the certbot docs that using the manual method doesn't support renew (unless you use hook scripts, via
--manual-auth-hook
and--manual-cleanup-hook
). Other alternative is just to use the manual method again when it comes time to renew.The scenario I'm thinking of is where the server is private but has a public DNS name, so the DNS TXT Challenge is the only option. (original cert and renewals). For automation, perhaps the certbot could run on the DNS (bind) server, and part of the cleanup/deploy hook script could push the new cert to the private server.
LetsEncrypt have revoked around 3 million certs last night due to a bug that they found. Are you impacted by this, Check out ?
DevTo
[+] dev.to/dineshrathee12/letsencrypt-...
GitHub
[+] github.com/dineshrathee12/Let-s-En...
LetsEncryptCommunity
[+] community.letsencrypt.org/t/letsen...
Wow thank you this worked for me.
Got tailscale installed.
Just did commands like this to get my own domain with https and tailscale.
apt install certbot
certbot --manual --preferred-challenges dns certonly -d domain.com \
certbot --apache
That's it 3 lines. the domain.com replace with your own domain name.
The 2nd line will ask you things you should know about your own server.
Thank you been working on this for 3 weeks now wanted to get https with my own domain name and Tailscale.
Excellent article.
I just have question though. I am using internal openstack cloud.
It has way to add DNS Zones and Record set.
I am not sure how to add the certbot DNS TXT record.
Any ideas?