Zero downtime with Let's Encrypt
Introduction
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.
/etc/pf.conf
First, lets redirect requests from special IP's to 80 and 443 to another port (8443 in my case).
table <letsencrypt> persist file "/etc/letsencrypt.pf" 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.
/etc/letsecnrypt.pf
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.
outbound1.letsencrypt.org outbound2.letsencrypt.org acme-staging.api.letsencrypt.org acme-v01.api.letsencrypt.org
IPs get resolved and loaded into letsencrypt
table automaticly.
Or load it manually
pfctl -tletsencrypt -Ta -f /etc/letsencrypt.pf
Beware: those IPs may change frequently. I suggest you to reload them periodically.
lego
And now, the client
go get -u github.com/xenolf/lego lego -m another@example.com --port 8443 -d example.com run
And that's all.
Conclusion
This setup has several benefits.
- you don't need to run verification client as
root
any more (unprivileged port) - your web-server is still running and serving clients
- your web-server configuration remains intact, as none automatical tool corrupts it
- you get your certs with zero downtime
References
github.com/letsencrypt/acme-spec/issues/33
letsencrypt.github.io/acme-spec/
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>
github.com/letsencrypt/acme-spec/issues/33#issuecomment-142408880