Using Let’s Encrypt Certs with Plesk

During the setup phase of this blog I was looking for an affordable way to secure traffic (SSL/TLS). Everybody is talking about Let’s Encrypt these days. And it’s free. So why not give it a spin.

I am using Plesk to administrate my webserver. The good thing is that Plesk supports “Let’s Encrypt” certificates out of the box:

Plesk requests a certificate from Let’s Encrypts servers. As long as you are maintaining your DNS records with Plesk on the same server this works fantastic. But not in my case. I am using an external DNS provider. And that’s the point where things start to get a little tricky. In order to verify that you are the domain owner LE uses a authentication protocol called ACME (Automatic Certificate Management Environment). This requires temporarily adding a TXT entry to your DNS records. The entry’s name looks something like this:

_acme-challenge.www.example.org. 300 IN TXT "fjg8Yp...Rg72jK"

You can enter this using the DNS provider’s admin portal. But since certificates issued by Let’s encrypt need to be renewed every 90 days this is not really a maintainable solution. You definitely want some kind of automated process here.

In general, certbot seems to be a good solution. But I wanted a less intrusive method that does not interfere with Plesk. (Plesk uses it’s own modified version of certbot.) Since I haven’t found much more information about this use case, I came up with my own little workflow.

Install lego

Lego? Right! Lego! It’s a small command line tool written in Go. This tool handles the cert request and the ACME challenge propagation to your DNS provider.

You can get the binaries here:
https://github.com/go-acme/lego/releases

Most likely you’ll need the Linux/amd64 version:
https://github.com/go-acme/lego/releases/download/v4.0.1/lego_v4.0.1_linux_amd64.tar.gz

I am using INWX as DNS provider. To find out more about other providers please see the Lego documentation. Make sure to adapt user, passwords and domains according to your needs.

1. Create a new folder:

sudo mkdir /opt/lego

2. Copy the tar file to that directory.

3. Extract the tar file:

sudo tar xvfz lego_v4.0.1_linux_amd64.tar.gz

4. Request your certificate from Let’s Encrypt:

I am using the domain “example.org” only as example (hence the name). Please replace all occurances in the following scripts and commands to match your domain. I am creating a certificate for the top-level domain itself and a wildcard certificate to cover all subdomains. That is my use-case. You might want to change this according to your needs.

INWX_USERNAME=<Username> \
INWX_PASSWORD=<Password> \
/opt/lego/lego --dns inwx --key-type rsa2048 --domains "example.org" --domains "*.example.org" --email "info@example.org" --cert.timeout 180 --dns.disable-cp run"

5. Create renew_cert.sh script file:

#!/bin/bash
# This scripts updates your cert if end date is <= 30 days.
days=30

INWX_USERNAME=<Username> \
INWX_PASSWORD=<Password> \
/opt/lego/lego --dns inwx --key-type rsa2048 --domains "example.org" --domains "*.example.org" --email "info@example.org" --dns.disable-cp renew --days $days --renew-hook "/opt/lego/on_cert_renewed.sh"

6. Create on_cert_renewed.sh script file:

#!/bin/bash
# This script copies your key and certificate in one file, which will be used by Apache.

cat /opt/lego/.lego/certificates/example.org.key > /opt/lego/.lego/certificates/example.org.final.crt
cat /opt/lego/.lego/certificates/example.org.crt >> /opt/lego/.lego/certificates/example.org.final.crt
sudo apache2ctl graceful

7. Set owner and file rights:

sudo chmod 700 /opt/lego/renew_cert.sh
sudo chmod 700 /opt/lego/on_cert_renewed.sh

8. In Plesk (“YourDomain” > “Apache & nginx Settings”):

In “Additional directives for HTTPS” add the following two lines:

SSLCertificateFile /opt/lego/.lego/certificates/example.org.final.crt
SSLCACertificateFile /opt/lego/.lego/certificates/example.org.issuer.crt

9. In Plesk (“Tools & Settings” > “Scheduled Tasks (Cron jobs)”)

Create a new daily Job and set the command to: /opt/lego/renew_cert.sh

For security reasons you might want to create a custom user to launch your script and use that user to execute the cron job.

Conclusion

If you’re using an external DNS provider like me, you could use this method to create a Let’s Encrypt certificate. A custom cron job will start a renew script on a daily basis to update your certificate only when needed.