Skip to content

Instantly share code, notes, and snippets.

@omushpapa
Last active February 1, 2024 06:15
Show Gist options
  • Save omushpapa/2c61f5495e89a288ca9934d80110c0a1 to your computer and use it in GitHub Desktop.
Save omushpapa/2c61f5495e89a288ca9934d80110c0a1 to your computer and use it in GitHub Desktop.
How to configure SSL using LetsEncrypt and Certbot on Apache in Ubuntu 16.04

How to setup Let's Encrypt for Apache on Ubuntu 16.04

In the following, we're setting up mydomain.com.

Challenges are served from /var/www/letsencrypt.

Apache snippets

First we create two snippets (to avoid duplicating code in every virtual host configuration).

Create a file /etc/apache2/snippets/letsencrypt.conf containing:

location ^~ /.well-known/acme-challenge/ {
	default_type "text/plain";
	root /var/www/letsencrypt;
}

Create a file /etc/apache2/snippets/ssl.conf containing:

SSLEngine 					on
SSLCertificateFile    		/etc/letsencrypt/live/mydomain.com/cert.pem
SSLCertificateKeyFile 		/etc/letsencrypt/live/mydomain.com/privkey.pem
SSLCertificateChainFile 	/etc/letsencrypt/live/mydomain.com/fullchain.pem

Header always 	set 	Strict-Transport-Security "max-age=15768000"
 
RequestHeader 	append 	"X-Forwarded-Proto" "https"
RequestHeader 	set 	"X-Forwarded-Ssl" "on"

SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLHonorCipherOrder on
SSLCompression off
SSLSessionTickets off

SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)

Create the folder for the challenges:

sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge

Apache virtual hosts (HTTP-only)

We don't have a certificate yet at this point, so the domain will be served only as HTTP.

Create a file /etc/apache2/sites-available/mydomain.conf containing:

<VirtualHost *:80>
        ServerName mydomain.com
        <fill in the rest here>
        
        Include /etc/apache2/snippets/letsencrypt.conf
        
</VirtualHost>

<VirtualHost *:443>
        ServerName mydomain.com
        <fill in the rest here>
        
</VirtualHost>

Enable the site:

rm /etc/apache2/sites-enabled/default # I bet this was done already
ln -s /etc/apache2/sites-available/mydomain.conf /etc/apache2/sites-enabled/mydomain.conf

And reload Apache:

sudo apachectl -k graceful

Certbot

Install the package:

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot

Note: there is also a letsencrypt package in APT, but it's a much older version of the client.


Get the certificate

Request the certificate (don't forget to replace with your own email address):

certbot certonly --webroot --agree-tos --no-eff-email --email YOUR@EMAIL.COM --config-dir /etc/letsencrypt --logs-dir /var/log/letsencrypt -w /var/www/letsencrypt -d www.domain.com -d domain.com

It will save the files in /etc/letsencrypt/live/www.mydomain.com/.

Note: The flag --no-eff-email opts out of signing up for the EFF mailing list, remove the flag if you'd like to signup.


Apache virtual hosts (HTTPS-only)

Now that you have a certificate for the domain, switch to HTTPS by editing the file /etc/apache2/sites-available/mydomain.conf and replacing contents with:

<VirtualHost *:80>
        ServerName mydomain.com
        <fill in the rest here>
        
        Include /etc/apache2/snippets/letsencrypt.conf
        
        Redirect permanent / https://mydomain.com/
</VirtualHost>

<VirtualHost *:443>
        ServerName mydomain.com
        <fill in the rest here>
        
        Include /etc/apache2/snippets/ssl.conf
</VirtualHost>

Then reload Apache:

sudo apachectl -k graceful

Automatic renewal using Cron

According to EFF:

The Certbot packages on your system come with a cron job that will renew your certificates automatically before they expire.

Hence, you don't need to worry about creating a cronjob for renewal.

Nevertheless, you can test the renewal by running:

certbot renew --dry-run

Conclusion

Congratulations, you should now be able to see your website at https://www.mydomain.com

You can now also test that your domain has A+ SLL rating:

I would also recommend setting up content-specific features like Content Security Policy and Subresource Integrity:

If Let's Encrypt is useful to you, consider donating to Let's Encrypt or donating to the EFF.

Thanks to cecilemuller for her nginx intro.

@mike503
Copy link

mike503 commented Jul 10, 2019

Your /etc/apache2/snippets/letsencrypt.conf is for nginx, not Apache.

@marie-dk
Copy link

marie-dk commented Dec 4, 2019

Like mike503 said... look under "Apache Snippets". The first codeblock is for nginx... Please correct it.

@shadowdestiny
Copy link

shadowdestiny commented Mar 5, 2020

#solution:

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

@Altrue
Copy link

Altrue commented Jun 4, 2022

Doesn't work, predictably.

First off, SSLStaplingCache isn't a VirtualHost option so it has nothing to do in a snippet injected inside a VirtualHost.

Second, if you only include the snippet inside the *:80 VirtualHost, then when accessing the site through *:443 directly, SSL will not be enabled...

Honestly, this snippet is doing more harm than good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment