← Back to the Build Log How I run things

How I get a wildcard SSL cert when my ISP blocks port 80

D
Daniel · Apr 25, 2024 · 4 min read
A straight road to a server blocked by a barrier gate, with a second path curving around it through a DNS cloud to reach the server, which carries a padlock shield

My home ISP blocks port 80. That sounds like a small thing until you go to put a real SSL certificate on something you host at home, and the usual path quietly stops working.

The default way to get a free certificate from Let's Encrypt is the HTTP-01 challenge. Their servers reach back to your machine on port 80, see a file they asked you to put there, and hand you the certificate. Clean, fast, automated. It also depends on port 80 being open to the internet, and on a residential connection it often isn't. Mine is closed and there is nothing I can do about it from my side.

The way around it is the DNS-01 challenge. Instead of proving you control the server by answering on port 80, you prove you control the domain by dropping a TXT record into DNS. No inbound port needed. As a bonus, DNS-01 is the only challenge that can issue a wildcard certificate, so one cert covers every subdomain at once and I stop juggling a separate cert per service.

Setting it up

I do all of this SSH'd into the box from TerminalNexus, which is where I run the server from day to day anyway.

First a place for the logs, then Certbot itself:

sudo mkdir /var/log/letsencrypt/
sudo apt install certbot

Then I kick off the request in manual mode:

certbot certonly --manual

Certbot asks for an email for expiry notices and to accept the terms. When it asks for the domain, this is where you ask for the wildcard:

*.yourdomain.com

The TXT record, and the part where patience matters

For DNS-01, Certbot hands you a value to publish as a TXT record under this name on your domain:

_acme-challenge

The value it gives you looks like a random string:

o7mU8KwvI7A1_phmxzrHOIA9jaGSOjkI-ngCRbSdhpc

You add that to your DNS provider, and then you wait. This is the step that bit me the first time. Do not let Certbot continue until the record has actually propagated. Depending on your provider that can be a few minutes or close to an hour. If you hit enter too early, the check fails and you start the whole thing over.

So I confirm it is live before continuing, two ways. The quick one is Google's Admin Toolbox dig page, which queries the TXT record for you in the browser:

https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.yourdomain.com

The other is from the terminal:

dig -t txt _acme-challenge.yourdomain.com

When the answer section comes back with the same value you published, you are good to let Certbot finish:

;; ANSWER SECTION:
_acme-challenge.yourdomain.com. 0 IN TXT "AxSzdAxR3yyJYok3KkuIRwod82Ld5MhYuH4oJ8"

Renewal without thinking about it

A certificate you have to remember to renew is a certificate that expires on a weekend. I let cron handle it:

sudo crontab -e

And add a line that runs twice a day:

certbot renew --quiet --post-hook "systemctl reload nginx"

Twice daily sounds like a lot for something that only matters every couple of months, but it means a transient failure has plenty of chances to recover long before anything actually expires. The odd minute, 4:47, is just to stay off the top of the hour where everyone else points their renewals. The post-hook is the important part: nginx only reloads after a renewal actually succeeds, so a failed renew never knocks the running site offline.

That is the whole trick. A blocked port 80 looks like a wall when you first hit it, but DNS-01 walks straight around it, and you come out the other side with a wildcard cert and renewals you never have to touch again.

Thanks for reading. If your ISP does something stranger than mine, I would like to hear about it in the comments.

Comments