My goal when moving everything onto new servers was to also use the brilliant service from Let’s Encrypt to encrypt web traffic. Of course, Let’s Encrypt doesn’t provide the same kind of verification to end users of the validity of the identity of a site as a service such as Digicert or Thoat but these services generally charget about €100 per certificate per year so for sites such as this, it’s not necessary.

I love Let’s Encrypt. Creating the certificate is easy. So too is renewing it. It’s all just so straight forward! Plus it’s all done through either the ISPConfig UI or through a shell.

This leads me to the reason for this post. I’ve found forums with people saying that ISPConfig 3.1.3 wasn’t assigning newly created certificates. But I just couldn’t figure out why. I didn’t want to go onto the unstable branch of ISPConfig where this problem has been fixed so I assumed that creating the cert using the shell would be straight forward. I’ve done this quite a few times before. The certbot package handles this.

The problems started here. I got errors like this:

[Errno 2] No such file or directory: ‘.well-known/acme-challenge/NCvDRv3…’

That gave me the idea to check {WebsiteName}/web/.well-known/acme-challenge. The owner was root so I changed it to the website user and related group. I then added a test file and tried to access it using HTTP. This didn’t work.

Then I remember that NGINX is set up on this server to allow specific URL types. WordPress is the CMS that is in use on this server for the most part so the rules are defined to only allow WordPress generated URL’s. My expectation is this would stop malware infecting sites. Based on experience I’ve had with WordPress vulnerabilities giving rise to exploits that escentially gave file system access. Malware would then be placed into a content directory where it would be caught by search engines.

So I tried to put in a location rule that would allow .well-known/acme-challenge. This still didn’t work.

I did a bit more digging and found that ISPConfig had already done something similar on the virtual host config file. So although I was being smart and modifying the main NGINX config for the server with the expectation that I was going to need this functionality for every site that I’m hosting, my change was being overridden by the virtual host settings defined by ISPConfig.

Once I figured that out, the change to the command was simple.
Change from

certbot certonly –webroot -w /var/www/{SiteName.tld}/web -d {SiteName.tld} -d www.{SiteName.tld}

Change to

certbot certonly –webroot -w /usr/local/ispconfig/interface/acme -d {WebSite.tld} -d www.{WebSite.tld}

It ran perfectly.

The next few challenges were with configuring the virtual host. Again, this stemmed from the fac that ISPConfig was my preference for handling all of this so it’s config got in the way or at the very least pointed me in the wrong direction initially.
Firstly, when it generated the certificates, it put them into the virtual directory under /var/{WebsiteName.tld}/certs/ But it added .key files. Let’s Encrypt created .pem files. So I didn’t want to take the differences at face value, I wanted to make sure that the differences were just coincidental.
Modifying the paths to point instead to /etc/letsencrypt/live/{WebsiteName.tld/cert.pem and Privkey.pem was obvious. Once that was done NGINX handled HTTPS traffic as expected. Here’s the related certificate lines:

listen *:443 ssl;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_certificate /etc/letsencrypt/live/{WebsiteName.tld}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{WebsiteName.tld}/privkey.pem;

The last part then was to make all HTTP traffic redirect to HTTPS. This was quite straight forward as well. I just added a second server block to the top of the {WebsiteName.tld.vhost} file in /etc/nginx/sites-available/ with the following entries.

server {
listen *:80;
server_name {WebsiteName.tld} www.{WebsiteName.tld};
return 301 https://www.{WebsiteName.tld}$request_uri;
}

Check your configuration:

service nginx configtest

Restart the NGINX service when ready.

service enginx restart

If something goes wrong, check the related logs:

systemctl service nginx.status

I hope this helps you. I didn’t get to the bottom of why ISPConfig isn’t associating the right certificate to the virtual host. That’s for another time I suppose.


Note on 22nd February 2019.


I was encountering an annoying problem when maintaining this site through the WordPress app. I was getting Curl errors relating to SSL. A bit of digging around showed that the intermediat certificate wasn’t found. This Digicert page was very useful in verifying that yes, something was wrong with my certificates on these domains. The problem was simple. I had specified cert.pem instead of fullchain.pem so the issuing certificate authority wasn’t included in the cert. I should have known this was going to cause issues.