Zero downtime with Let's Encrypt


Apparently there is no way to define an alternative port for Let's Encrypt verification process. ACME specification states explicitly that those must be 80 and 443 ports.

Thus, with production servers running, you either have to tolerate downtime or let Let's Encrypt client tamper with your precious configs. None of both is very desirable.

Opposite to the official client, lego client lets you define a custom port, you can then redirect the verification traffic to. And here is, how I done it.


First, lets redirect requests from special IP's to 80 and 443 to another port (8443 in my case).

table <letsencrypt> persist file "/etc/"

pass in quick inet proto tcp from <letsencrypt> \
    to port {http, https} rdr-to egress port 8443

Please note, that we are redirecting to external IP (egress interface), since there is no way to tell lego to listen on localhost. You can only define a custom port.


This file contains special URIs, where verification requests are coming from. The first two entries are important. The other two are only for completeness sake here.

IPs get resolved and loaded into letsencrypt table automaticly. Or load it manually

pfctl -tletsencrypt -Ta -f /etc/

Beware: those IPs may change frequently. I suggest you to reload them periodically.


And now, the client

go get -u
lego -m --port 8443 -d run

And that's all.


This setup has several benefits.


Similar solution for Linux

iptables --table nat --append PREROUTING --protocol tcp \
    --source <Validation Authority IP address> --dport 443 \
    --jump REDIRECT --to-ports <ACME client port>
By Dimitri Sokolyuk
Related articles