Let's Encrypt and Anycast

I've got all the three locations from BuyVM in order to deploy my personal website on the freely provided anycast IP Address both for DNS and HTTP.

I had issues finding a proper way to verify the main domain in all the three location in order to let every node renew its certificate automatically with acme.sh without the need of a master node or any custom script/code.

The requirements:


Every node must have a different private key
The nodes do not interact with each other
Must work with acme.sh out of the box
Must renew automatically


Although the solution is simple, it took me a couple of days to think of it so that's the reason why I'm sharing it.

Assume you have three nodes:

lu.mydomain.com
lv.mydomain.com
ny.mydomain.com


Here's a sample nginx config for lu.mydomain.com node with only the relevant parts:

# Default server to redirect to https main domain, when handling non existant *.mydomain.com subdomains
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 $scheme://mydomain.com$request_uri;
}

# Server for Let's Encrypt validation
server {
listen 80;
listen [::]:80;
server_name mydomain.com www.mydomain.com lu.mydomain.com;

location @anycast_redirect {
return 301 $scheme://lv.mydomain.com$request_uri;
}

location /.well-known {
error_page 404 = @anycast_redirect;
alias /var/www/mydomain.com/acme/.well-known;
}

root /var/www/mydomain.com/htdocs;

location / {
return 301 https://mydomain.com$request_uri;
}
}

# Https server with everything else
server {
listen 443 ssl http2 default_server;

[...]


In the HTTP-01 Acme specification there's written that the validation server follows up to 10 redirects so this approach can work with a limited number of servers in the anycast pool.
The logic is that each server, if trying to verify a nonexistent Acme challenge will automatically redirect to another one in loop:

lu.mydomain.com -> lv.mydomain.com
lv.mydomain.com -> ny.mydomain.com
ny.mydomain.com -> lu.mydomain.com


With this configuration, each node can now issue and renew with:

acme.sh --ecc --issue/--renew -d mydomain.com -w /var/www/mydomain.com/acme/ --fullchain-file /etc/ssl/certs/mydomain.com.pem --key-file /etc/ssl/private/mydomain.com.key


Thoughts? Is there a simpler solution? This is of course an experiment for an experimental personal website that doesn't even need to be anycast in the first place

Top News