It was 3:23PM.

I was reading a tutorial about something unrelated when I was told that setting up a free SSL cert and HTTPS with NGINX is easy. That there’s something nifty now called Lets Encrypt, and that they just give out free certs like candy, and make it easy to config too.

I remember being told that that was a daunting task years ago. I don’t know all that much about HTTPS, but I’ve been on a little bit of an encryption kick lately. There was no way I was going to pass up the chance to add a little extra security to the internet!

So I go to

I’m told I should use certbot, since I have shell access to my server.

At I tell a cute robot-key-creature what web server and operating system I’m using — NGINX and CentOS7. The cute robot tells me to add a repository I already added years ago to my yum repo list, so I skip that step and simply run sudo yum install certbot-nginx. It works.

The site tells me I can go all-in via sudo certbot --nginx, in which case the package will go ahead and edit my NGINX conf files itself, or I can just use the certbot to get the cert and set up the confs myself. I went all in.

I was given a few basic prompts — I was asked for my email and had to agree to ToS — and then it got cool. It asked me which hosts I wanted to set up. I didn’t have to do anything and there was a list of what I believe are all the domains pointing to my IP, including with “subdomain” specificity. I chose to only set up and…

And then it failed validation.

The error message:

Failed authorization procedure. (tls-sni-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Error getting validation data, (tls-sni-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Error getting validation data

My firewall wouldn’t let the certbot reach out and do what it needed to do. Being impatient, I temporarily turned off my firewall rather than configuring it to allow HTTPS and then I re-ran the certbot. I got another prompt asking me whether or not I wanted to force the site(s) to direct to HTTPS and that was that. There was my site, running HTTPS, and doing a 301 redirect for the HTTP URLS!

I did have to enable HTTPS on my firewall and restart it. Running sudo firewall-cmd --permanent --add-service=https and sudo service firewalld restart did it!

My site was running HTTPS and only HTTPS by 4pm. It was glorious.

Which isn’t to say there weren’t other problems. My site wasn’t actually running properly.

Yes, certbot inserted the rather simple nginx confs in the right spot to get my site to serve HTTPS and redirect HTTP. This is surprising, really, as I have a rather odd nginx setup; I use nginx both as my server and my cache server, with one server block listening on port 80 and cacheing things and an upstream server block listening on and serving files or whatever PHP gives it. Based on the console output from certbot, it did experience some confusion with my conf files, but it nonetheless accurately put this in the right server block (the top-level one):

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

if ($scheme != "https") {
return 301 https://$host$request_uri;
} # managed by Certbot

# Redirect non-https traffic to https
# if ($scheme != "https") {
# return 301 https://$host$request_uri;
# } # managed by Certbot

But when that first server block handed off the request to the second server block, it didn’t hand off the information explaining that the original request was HTTPS, and the PHP generating my site at the end certainly had no knowledge of whether or not the site was HTTPS. As I understand it, this is a potential problem with HTTPS and proxies for frameworks other than WordPress, but it is definitely a problem for WordPress.

Completely expectedly, I had to go through the usual process of changing WP over to using the new URL with the https in it instead of HTTP, but that’s just a given part of the process of working with WordPress. Once I did that, the site was mostly working — except for the dashboard. If you try hitting the HTTPS version of the admin section of a WordPress site, WordPress wants $_SERVER[‘HTTPS’] to be set. It has to be set, I believe, to either 1 or ‘ON’. Otherwise you’ll get an endless redirect loop.

There are a number of unpleasant ways to get around this, and I’m not certain this is the one I’m going to go with in the long-term. Maybe I’ll just finally give in and stop using WP. But in the meantime, I simply added this in with the other stuff in my nginx config directing extra variables to be handed off to fast_cgi by NGINX: fastcgi_param HTTPS ON; and voila, no more redirects!

Thankfully, in writing this, I went back to look at the certbot website, and realized there’s an additional step I have to do, some time in the next 90 days. Apparently LetsEncrypt certs expire every 90 days, and while it’s at least as straightforward to renew them, one still has to do so. The certbot recommends setting up a process that tries to renew them twice a day every day. Better safe than sorry and all that.

Hopefully I’ll remember to do that tomorrow.