// Tutorial //

How To Secure Apache with Let's Encrypt on Ubuntu 16.04

Published on April 21, 2016
Default avatar
By Erika Heidi
Developer Advocate
How To Secure Apache with Let's Encrypt on Ubuntu 16.04
Not using Ubuntu 16.04?Choose a different version or distribution.
Ubuntu 16.04

Introduction

This tutorial will show you how to set up a TLS/SSL certificate from Let’s Encrypt on an Ubuntu 16.04 server running Apache as a web server.

SSL certificates are used within web servers to encrypt the traffic between the server and client, providing extra security for users accessing your application. Let’s Encrypt provides an easy way to obtain and install trusted certificates for free.

Prerequisites

In order to complete this guide, you will need:

  • An Ubuntu 16.04 server with a non-root sudo-enabled user, which you can set up by following our Initial Server Setup guide
  • The Apache web server installed with one or more domain names properly configured through Virtual Hosts that specify ServerName.

When you are ready to move on, log into your server using your sudo-enabled account.

Step 1 — Install the Let’s Encrypt Client

Let’s Encrypt certificates are fetched via client software running on your server. The official client is called Certbot, and its developers maintain their own Ubuntu software repository with up-to-date versions. Because Certbot is in such active development it’s worth using this repository to install a newer version than Ubuntu provides by default.

First, add the repository:

  1. sudo add-apt-repository ppa:certbot/certbot

You’ll need to press ENTER to accept. Afterwards, update the package list to pick up the new repository’s package information:

  1. sudo apt-get update

And finally, install Certbot from the new repository with apt-get:

  1. sudo apt-get install python-certbot-apache

The certbot Let’s Encrypt client is now ready to use.

Step 2 — Set Up the SSL Certificate

Generating the SSL certificate for Apache using Certbot is quite straightforward. The client will automatically obtain and install a new SSL certificate that is valid for the domains provided as parameters.

To execute the interactive installation and obtain a certificate that covers only a single domain, run the certbot command like so, where example.com is your domain:

  1. sudo certbot --apache -d example.com

If you want to install a single certificate that is valid for multiple domains or subdomains, you can pass them as additional parameters to the command. The first domain name in the list of parameters will be the base domain used by Let’s Encrypt to create the certificate, and for that reason we recommend that you pass the bare top-level domain name as first in the list, followed by any additional subdomains or aliases:

  1. sudo certbot --apache -d example.com -d www.example.com

For this example, the base domain will be example.com.

If you have multiple virtual hosts, you should run certbot once for each to generate a new certificate for each. You can distribute multiple domains and subdomains across your virtual hosts in any way.

After the dependencies are installed, you will be presented with a step-by-step guide to customize your certificate options. You will be asked to provide an email address for lost key recovery and notices, and you will be able to choose between enabling both http and https access or forcing all requests to redirect to https. It is usually safest to require https, unless you have a specific need for unencrypted http traffic.

When the installation is finished, you should be able to find the generated certificate files at /etc/letsencrypt/live. You can verify the status of your SSL certificate with the following link (don’t forget to replace example.com with your base domain):

https://www.ssllabs.com/ssltest/analyze.html?d=example.com&latest

You should now be able to access your website using a https prefix.

Step 3 — Verifying Certbot Auto-Renewal

Let’s Encrypt certificates only last for 90 days. However, the certbot package we installed takes care of this for us by running certbot renew twice a day via a systemd timer. On non-systemd distributions this functionality is provided by a cron script placed in /etc/cron.d. The task runs twice daily and will renew any certificate that’s within thirty days of expiration.

To test the renewal process, you can do a dry run with certbot:

  1. sudo certbot renew --dry-run

If you see no errors, you’re all set. When necessary, Certbot will renew your certificates and reload Apache to pick up the changes. If the automated renewal process ever fails, Let’s Encrypt will send a message to the email you specified, warning you when your certificate is about to expire.

Conclusion

In this guide, we saw how to install a free SSL certificate from Let’s Encrypt in order to secure a website hosted with Apache. We recommend that you check the official Let’s Encrypt blog for important updates from time to time, and read the Certbot documentation for more details about the Certbot client.

If you’ve enjoyed this tutorial and our broader community, consider checking out our DigitalOcean products which can also help you achieve your development goals.

Learn more here


About the authors
Default avatar
Developer Advocate

Dev/Ops passionate about open source, PHP, and Linux.

Still looking for an answer?

Was this helpful?
10 Comments

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Please, for the sake of the letsencrypt servers, don’t just copy the crontab config from this article, but rather put in some other arbitrary numbers (another weekday & time)! Otherwise thousands of clients will renew exactly at the same time every Monday at 2:30 am, which will potentially DDoS the servers.

If your get the following message : “Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA.” You need the following command : sudo certbot --authenticator standalone --installer apache -d example.com -d www.example.com --pre-hook "service apache2 stop" --post-hook "service apache2 stop"

To read more about this issue : https://github.com/certbot/certbot/issues/5405#issuecomment-356498627

just a heads up that this generates an additional config file for your virtual host, with -le-ssl.conf appended on the end. I didn’t realise and spent ages editing my virtualhosts config file to allow htaccess override and it wasn’t working. I was editing:

/etc/apache2/sites-enabled/website.com.conf

when i should’ve edited:

/etc/apache2/sites-enabled/website.com-le-ssl.conf

Hopefully that’ll save someone else a headache!

The last step for cert generation above does not work anymore. Please update the command

sudo certbot --authenticator standalone --installer apache --pre-hook “apachectl -k stop” --post-hook “apachectl -k start”

Or visit certbot eff website to see updated steps.

Help me

sudo certbot --apache -d example.com i can not

show Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA.

please T_T

Generating certificates this way is great, but it leaves you open to your cron accidentally breaking or your renewal script not working as you expected. To get around this you should check your SSL certificate regularly to ensure that it’s been renewed using a service like TrackSSL that notifies you if your certificate is close to expiration.

As a newbie to all things Ubuntu/Wordpress, I really appreciate the above article but hoped to ask the community to clarify a few things. I already have a functioning Wordpress site running on ubuntu 16.04 server with Wordpress installed using the really helpful DO one click install. I also have 5 domains all re-directing to my primary domain using CNAME aliases activated within the DO control panel. It all works well but I hope to make use of LetsEncrypt to enforce secure only access. Having (unsuccessfully) played around with activating LetsEncrypt on one of the subdomains, I hoped someone could help me with the following queries:

  1. As things stand if anyone types any of my subdomains into browser (for instance, www.mycompany.us, www.my company.co) the alias kicks in and takes you to www.mycompany.com. Also, both www.mycompany.com and http://mycompany.com resolve to mycompany.com in a browser, it all works well. I presume I only need to apply LetsEncrypt to my primary domain as the re-directs will push all requests (http or otherwise) to the https primary domain?
  2. I have went through the server setup guide and started to work through the ‘how to setup apache virtual hosts guide’. Do I need to create a new virtual hosts file for www.mycompany.com or can I amend the already existing 000-default.conf file to include server name, server alias and update serveradmin with my proper email address?
  3. The guide talks about creating a directory for new content and pointing Document Root to this, given i already have Wordpress content stored in the default location, presume I can keep DocumentRoot pointed to /var/www/html??
  4. Now onto this guide, once LetsEncrypt is installed, following running ‘sudo letsencrypt --apache -d mycompany.com -d www.mycompany.com’ - do I need to do anything within Wordpress to ‘tell’ Wordpress the certificate is available and web requests should be resolved as https??

Apols for the queries, hoping to get some nudges in the right direction:)

I followed this guide a few months back and everything is working correctly. However, I’m unable to update the Let’s Encrypt client using the command sudo git pull. Here is the output from my SSH session when running the command.

johners@JohnersBlogIPV6:/opt/letsencrypt$ sudo git pull
remote: Counting objects: 597, done.
remote: Compressing objects: 100% (98/98), done.
remote: Total 597 (delta 423), reused 358 (delta 358), pack-reused 141
Receiving objects: 100% (597/597), 218.72 KiB | 0 bytes/s, done.
Resolving deltas: 100% (453/453), completed with 126 local objects.
From https://github.com/letsencrypt/letsencrypt
   d05f53b..f544b03  master     -> origin/master
 * [new branch]      2558-test-fix -> origin/2558-test-fix
 * [new branch]      all-together-now -> origin/all-together-now
 * [new branch]      dedupe     -> origin/dedupe
 * [new branch]      doc-plugins-anchor -> origin/doc-plugins-anchor
   65605f7..44cf404  documentation_cleanup -> origin/documentation_cleanup
 * [new branch]      issue_2558 -> origin/issue_2558
 * [new branch]      issue_3282 -> origin/issue_3282
   e4f963d..5bf9b3a  multiple_vhosts -> origin/multiple_vhosts
 * [new branch]      nginx-space-preservation2 -> origin/nginx-space-preservation2
 * [new branch]      revert-3268-dialog-autosize -> origin/revert-3268-dialog-autosize
Updating 45e47f6..f544b03
error: Your local changes to the following files would be overwritten by merge:
        letsencrypt-auto
Please, commit your changes or stash them before you can merge.
Aborting

Any idea on what I should do to get my client to update without it losing my configuration (if that even happens)?

I had a working web app but after following this tutorial I get “Index of /” (which has my project files) when I use https. and when I use plain HTTP I get a blank “Index of /”

➜ ~ sudo certbot renew --dry-run Saving debug log to /var/log/letsencrypt/letsencrypt.log


Processing /etc/letsencrypt/renewal/aveindiadesigncollective.com-0001.conf


Cert not due for renewal, but simulating renewal for dry run Plugins selected: Authenticator apache, Installer None Renewing an existing certificate


new certificate deployed without reload, fullchain is /etc/letsencrypt/live/aveindiadesigncollective.com-0001/fullchain.pem



Processing /etc/letsencrypt/renewal/aveindiadesigncollective.com.conf


Cert not due for renewal, but simulating renewal for dry run Plugins selected: Authenticator webroot, Installer None Renewing an existing certificate


new certificate deployed without reload, fullchain is /etc/letsencrypt/live/aveindiadesigncollective.com/fullchain.pem



Processing /etc/letsencrypt/renewal/gaurang.co-0001.conf


Attempting to parse the version 1.9.0 renewal configuration file found at /etc/letsencrypt/renewal/gaurang.co-0001.conf with version 0.31.0 of Certbot. This might not work. Cert is due for renewal, auto-renewing… Could not choose appropriate plugin: The requested nginx plugin does not appear to be installed Attempting to renew cert (gaurang.co-0001) from /etc/letsencrypt/renewal/gaurang.co-0001.conf produced an unexpected error: The requested nginx plugin does not appear to be installed. Skipping.


Processing /etc/letsencrypt/renewal/gaurang.co.conf


Traceback (most recent call last): File “/usr/lib/python3/dist-packages/certbot/renewal.py”, line 68, in _reconstitute renewal_candidate = storage.RenewableCert(full_path, config) File “/usr/lib/python3/dist-packages/certbot/storage.py”, line 444, in init “file reference”.format(self.configfile)) certbot.errors.CertStorageError: renewal config file {} is missing a required file reference Renewal configuration file /etc/letsencrypt/renewal/gaurang.co.conf is broken. Skipping. The following certs could not be renewed: /etc/letsencrypt/live/gaurang.co-0001/fullchain.pem (failure)


** DRY RUN: simulating ‘certbot renew’ close to cert expiry ** (The test certificates below have not been saved.)

The following certs were successfully renewed: /etc/letsencrypt/live/aveindiadesigncollective.com-0001/fullchain.pem (success) /etc/letsencrypt/live/aveindiadesigncollective.com/fullchain.pem (success)

The following certs could not be renewed: /etc/letsencrypt/live/gaurang.co-0001/fullchain.pem (failure)

Additionally, the following renewal configurations were invalid: /etc/letsencrypt/renewal/gaurang.co.conf (parsefail) ** DRY RUN: simulating ‘certbot renew’ close to cert expiry ** (The test certificates above have not been saved.)


1 renew failure(s), 1 parse failure(s) ➜ ~

WHAT DO I DO? THIS IS THE ERROR I KEEP GETTING