Skip to content

Instantly share code, notes, and snippets.

@harryfinn
Last active November 12, 2023 10:21
Show Gist options
  • Save harryfinn/e36e41cdbfba5a6e1d69d6498a4fc5ee to your computer and use it in GitHub Desktop.
Save harryfinn/e36e41cdbfba5a6e1d69d6498a4fc5ee to your computer and use it in GitHub Desktop.
Instructions on how to setup a Letsencrypt SSL certificate on a WordPress site

Letsencrypt (for WordPress sites)

Note: This setup assumes you are running Ubuntu 16.04 OS with Apache 2.4.23, older versions of Ubuntu (i.e. 14.04) require minor configuration changes in order for this setup to work.

Setup

Follow the install instructions for certbot (letsencrypt's SSL manager) on https://certbot.eff.org/, making sure to select the correct server OS version.

Note: You only need to complete the Install section, then return to this README in order to setup your SSL

Registering an SSL

Once installed, run the following certbot command:

certbot certonly --webroot --webroot-path /var/www/html/ --renew-by-default -d yourdomainhere.com

Certbot has a lot of configuration options and when used with Apache, can automatically setup your SSL certificates without the need for apache configuration file amends, however, if using a service such as CloudFlare to manage your DNS and adding caching etc, the command above will be required in order to validate the SSL successfully. It's also recommend to use this command over the built in apache module (at this time) as it will grant great control over your site's SSL.

  • certonly is the command we are running, telling certbot to generate a letsencrypt SSL manually, i.e. without the apache configuration (we'll do this ourselves!)
  • --webroot is the type of authentication we want to use in order to check our domain against with the SSL. This option comes back to the CloudFlare issue, whereby a CloudFlare protected server won't respond with the origin server's IP address, but instead with a dynamic CloudFlare IP, causing the SSL to fail verification.
  • --webroot-path sets the root of your website, this should be where your apache configuration's DocumentRoot is pointing to.
  • --renew-by-default tells letsencrypt to attempt to automatically try to renew this SSL if it is already set and in need of renewal
  • -d sets the domain you which to assign this SSL to, multiple domains can be registered at the same time by passing additional -d flags after each domain.

After running the certonly command you should be prompted for an email address, used to notify you of upcoming SSL's due to expire and upon entering your email the process should complete with a success message similar to:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/byourdomainhere.com/fullchain.pem.
   Your cert will expire on 2017-03-01. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"

Configuring Apache site configs

Insure that the ssl module has been enabled on apache, to enable run a2enmod ssl then service apache2 restart. Without this module your apache configuration will not work and likely through the following error when attempting to restart: Invalid command 'SSLEngine'

Once the SSL has been setup for your domain, you need to update your apache site configuration with some additional rules to tell apache how to handle requests over https.

  • Swap into the apache sites available folder cd /etc/apache2/sites-available and open the config file for the site you have attached the SSL certificate to, i.e. nano/vi yourdomain.here.conf
  • As well as having a VirtualHost rule for port 80 (http traffic), we also need to add a VirtualHost rule for port 443 (https traffic). Using the example below, add the missing sections to your site's configuration (note you may have additional settings in your configuration, in which case, merge the rules below with your existing ones):

Note: If setting up your SSL for the first within WordPress (or any other system that requires activation of SSL before becoming active), comment out the Redirect permanent line in the seciton below until after this has been completed. Otherwise you might find yourself either locked out of the system before it is activated or in an endless redirect loop!

<VirtualHost *:80>
        ServerName yourdomainhere.com
        ServerAdmin me@yourdomainherec.om
        DocumentRoot /var/www/html
        
        Redirect permanent / https://yourdomainhere.com/
</VirtualHost>

<VirtualHost *:443>
        ServerName yourdomainhere.com
        ServerAdmin me@yourdomainhere.com
        DocumentRoot /var/www/html
        
        ErrorLog ${APACHE_LOG_DIR}/yourdomainhere.com-error.log
        CustomLog ${APACHE_LOG_DIR}/yourdomainhere.com-access.log combined
        
        SSLEngine On
        SSLCertificateFile /etc/letsencrypt/live/yourdomainhere.com/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/yourdomainhere.com/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/yourdomainhere.com/chain.pem
 
        Header always set Strict-Transport-Security "max-age=15768000"
 
        RequestHeader append "X-Forwarded-Proto" "https"
        RequestHeader set "X-Forwarded-Ssl" "on"
</VirtualHost>

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSLHonorCipherOrder on
SSLCompression off
SSLSessionTickets off

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

Note: if you are not using letsencrypt alongside Cloudflare & it's SSL, and you are happy for some older browsers/devices to be unsupported, you can use the following SSLCipherSuite value instead which will give a stronger encryption type cipher designed for modern browsers and devices:

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
  • The configuration above tells apache where your SSL certificates are and where to validate them when requests over https are made. You can now save this configuration file.
  • Update apache with service apache reload

Checking how long your SSL is valid for and renewing

I use a package called ssl-cert-check to allow me to check the expiry of my SSL certificates which is simple to use and outputs a simple to view data format.

First install ssl-cert-check with the following command: apt-get install ssl-cert-check

Now to view a certificates expiry date, use the following command: ssl-cert-check -c /etc/letsencrypt/live/yourdomainhere.com/cert.pem

This will return an output similar to the one below:

Host                                                   Status Expires    Days
------------------------------------------------------ ------ ---------- ----
FILE:/etc/letsencrypt/live/yourdomianhere.com/cert.pem Valid  Mar 1 2017 90

Certbot will allow you to renew your SSL when it is within 30 days of expiry, you can setup a cronjob/crontab task to perform this or simply run the the following command ./certbot-auto renew which will attempt to renew any and all certificates on the server.

Cron job renewal example

First run crontab -e (you may be prompted for which editor to use, use which even you'd prefer!). Once within the crontab file, add the following to the bottom of the file:

00 03 * * * certbot renew --quiet --renew-hook "service apache2 reload"

This will run every day at 3am, calling the certbot renew command, with a couple params to silence the output and to reload apache when the renew completes. This will ensure that once your site reaches 30 days before renewal, the SSL will be renewed without any manual input :)

Configuring WordPress

Install the Really Simple SSL plugin and go to the SSL settings page within the WP admin. Before clicking the Go ahead, activate SSL button, check that the plugin has recognised your SSL, it should display the following message An SSL certificate was detected on your site..

Due to the nature of the SSL setup, the default .htaccess rules may not always perform the correct redirects and require you to disable the plugin from editing your .htaccess file and add the rules manually.

Check which rule(s) may or may not apply for your site here = https://really-simple-ssl.com/knowledge-base/manually-insert-htaccess-redirect-http-to-https/

@philipt18
Copy link

In my sites available directory I have the following files:

000-default.conf
default-ssl.conf

Am I supposed to be editing one of these to add the virtual host info, or creating a new file?

@castaway
Copy link

If you only have one host running on your apache, you can use the 000-default..

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