Let’s Encrypt is a certificate authority created by the Internet  Security Research Group (ISRG). It provides free SSL certificates via a  fully automated process designed to eliminate manual certificate  creation, validation, installation, and renewal.

Certificates issued by Let’s Encrypt are trusted by all major browsers today.

In  this tutorial, we’ll provide a step by step instructions about how to  secure your Apache with Let’s Encrypt using the certbot tool on Ubuntu  18.04.


Make sure that you have met the following prerequisites before continuing with this tutorial:

Install Certbot

Certbot  is a fully featured and easy to use tool that can automate the tasks  for obtaining and renewing Let’s Encrypt SSL certificates and  configuring web servers. The certbot package is included in the default  Ubuntu repositories.

Update the packages list and install the certbot package:

sudo apt update

Generate Strong Dh (Diffie-Hellman) Group

Diffie–Hellman  key exchange (DH) is a method of securely exchanging cryptographic keys  over an unsecured communication channel. We’re going to generate a new  set of 2048 bit DH parameters to strengthen the security:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

If  you want, you can change the size up to 4096 bits, but in that case,  the generation may take more than 30 minutes depending on the system  entropy.

Obtaining a Let’s Encrypt SSL certificate

To  obtain an SSL certificate for the domain, we’re going to use the  Webroot plugin that works by creating a temporary file for validating  the requested domain in the ${webroot-path}/.well-known/acme-challenge directory. The Let’s Encrypt server makes HTTP requests to the  temporary file to validate that the requested domain resolves to the  server where certbot runs.

To make it more simple we’re going to map all HTTP requests for .well-known/acme-challenge to a single directory, /var/lib/letsencrypt.

The following commands will create the directory and make it writable for the Apache server.

sudo mkdir -p /var/lib/letsencrypt/.well-known

To avoid duplicating code create the following two configurations snippets:


Alias /.well-known/acme-challenge/ "/var/lib/letsencrypt/.well-known/acme-challenge/"
<Directory "/var/lib/letsencrypt/">
    AllowOverride None
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    Require method GET POST OPTIONS


SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder On
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
# Requires Apache >= 2.4
SSLCompression off
SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
# Requires Apache >= 2.4.11
SSLSessionTickets Off

SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"


The snippet above is using the chippers recommended by Cipherli.st, enables OCSP Stapling, HTTP Strict Transport Security (HSTS) and enforces few security‑focused HTTP headers.

Before enabling the configuration files, make sure both mod_ssl and mod_headers are enabled by issuing:

sudo a2enmod ssl

Next, enable the SSL configuration files by running the following commands:

sudo a2enconf letsencrypt

Enable the HTTP/2 module, which will make your sites faster and more robust:

sudo a2enmod http2

Reload the Apache configuration for changes to take effect:

sudo systemctl reload apache2

Now, we can run Certbot tool with the webroot plugin and obtain the SSL certificate files by typing:

sudo certbot certonly --agree-tos --email admin@example.com --webroot -w /var/lib/letsencrypt/ -d example.com -d www.example.com

If the SSL certificate is successfully obtained, certbot will print the following message:

 - Congratulations! Your certificate and chain have been saved at:
   Your key file has been saved at:
   Your cert will expire on 2018-10-28. 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

Now that you have the certificate files, edit your domain virtual host configuration as follows:


<VirtualHost *:80> 
  ServerName example.com
  ServerAlias www.example.com

  Redirect permanent / https://example.com/

<VirtualHost *:443>
  ServerName example.com
  ServerAlias www.example.com

  Protocols h2 http:/1.1

  <If "%{HTTP_HOST} == 'www.example.com'">
    Redirect permanent / https://example.com/

  DocumentRoot /var/www/example.com/public_html
  ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
  CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined

  SSLEngine On
  SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

  # Other Apache Configuration



With the configuration above, we are forcing HTTPS and redirecting from www to non-www version. Fell free to adjusts the configuration according to your needs.

Reload the Apache service for changes to take effect:

sudo systemctl reload apache2

You can now open your website using https://, and you’ll notice a green lock icon.

If you test your domain using the SSL Labs Server Test, you’ll get an A+ grade, as shown below:

Auto-renewing Let’s Encrypt SSL certificate

Let’s  Encrypt’s certificates are valid for 90 days. To automatically renew  the certificates before they expire, the certbot package creates a  cronjob that runs twice a day and automatically renews any certificate  30 days before its expiration.

Once the certificate is renewed we also have to reload the Apache service. Append --renew-hook "systemctl reload apache2" to the /etc/cron.d/certbot file so that it looks like the following:


0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew --renew-hook "systemctl reload apache2"


To test the renewal process, you can use the certbot --dry-run switch:

sudo certbot renew --dry-run

If there are no errors, it means that the renewal process was successful.


In  this tutorial, you used the Let’s Encrypt client certbot, to download  SSL certificates for your domain. You have also created Apache snippets  to avoid duplicating code and configured Apache to use the certificates.  At the end of the tutorial, you have set up a cronjob for automatic  certificate renewal.

If you want to learn more about how to use Certbot, their documentation is a good starting point.