I have a bunch of domains for which I want to provide improved delivery performance.
For this I want to create a set of geo distributed caching proxies.
In my current centralized setup I have one server which handles everything including traefik, and webservers and thus acme challenges for the domains managed by this one traefik instance. I have an acme.json where the certs are stored.
My idea was to create caching proxies and use traefik there too. This means, for a bunch of geo located domains, there are various locations which can handle a request, including acme challenges.
One idea is, that I can keep my centralized server and let it handle all the acme related requests.
But since acme is baked into traefik, I assume, I cannot just create a route for /.well-known requests which is transparently forwarded to the central server?
With an apache server I could e.g. use a bit of mod rewrite and mod proxy magic to forward the requests.
How is this done with distributed Traefik instances? Can this be done?
And the followup: When the certificates are updated on the central root server, how do I distribute them then to the geolocated Traefik proxies such that there is no downtime? Can I just rsync the acme.json and the geolocated Traefik instances will pick it up?
That's a complex topic Traefik community edition is not LetsEncrypt cluster enabled.
Lets go through the options you have with plain Traefik (no k8s):
Use a single Traefik instance to generate LetsEncrypt TLS certs with httpChallenge. Then all other instances would need to forward /well-known requests to the single instance. It would create the acme.json file.
a) You copy acme.json to all other Traefik instances. But the file is not watched, so you would need to restart Traefik.
or
b) You export the TLS certs from the acme.json file and provide them to the other instances via providers.file or providers.http. That can be watched, no restart required.
Use every Traefik instance to create their own LetsEncrypt TLS cert with dnsChallenge. But note that LE has strict limits, you can only create 5 TLS certs for a domain a week. So max 5 instances, and you better make sure to have a backup of the cert, in case a node is lost.
Create the TLS cert externally, like cert-manager is used with k8s. Use certbot or acme.sh or something and just provide the certs via dynamic config through providers.file or providers.http. You can provide dynamic config with reference to the files (handle multiple files) or inline the TLS certs into the config.
a) Proof of concept using certbot and providers.http, so no files are exchanged. But I am not sure what happens when the service is unreachable or goes down, if Traefik will keep using the existing certs.
b) Example scripts using acme.sh with dnsChallenge for wildcards and providers.file with a single file. You still need to distribute the file to all nodes. Note that LetsEncrypt wants to reduce the expiration time of certs from 3 months to a couple of days, so you should automate this.
Create TLS certs:
#!/bin/zsh
# Use a here document to define a list of domains
DOMAINS=$(cat <<EOF
example.com
example2.com
EOF
)
# Iterate over each domain
for DOMAIN in ${(f)DOMAINS}; do
echo "\n\n\n********** DOMAIN ${DOMAIN} **********\n\n\n"
# Run the acme.sh command for each domain
PROVIDER_USER="abc" \
PROVIDER_PASSWORD="123" \
/Users/user/.acme.sh/acme.sh \
--force \
--issue \
--server letsencrypt \
--dns dns_PROVIDER \
--home . \
-d "$DOMAIN" -d "*.$DOMAIN" \
--cert-file "./certificates/$DOMAIN.cer" \
--key-file "./certificates/$DOMAIN.key" \
--fullchain-file "./certificates/$DOMAIN.pem" \
sleep 2
done
Generate Traefik dynamic config file:
#!/bin/bash
# Define the certificates directory and the output file
CERT_DIR="./certificates"
FILE="./traefik-tls.yml"
# Start writing the Traefik dynamic configuration file
echo "TRAEFIK TLS FILE GENERATION"
printf "tls:\n options:\n default:\n minVersion: VersionTLS12\n certificates:\n" > $FILE
# Find all .key files in the certificates folder, strip the .key extension, and iterate over them
for KEY_FILE in $(find $CERT_DIR -maxdepth 1 -name "*.key" -type f | sort); do
# Remove the .key extension to get the domain name (or file prefix)
DOMAIN=$(basename "$KEY_FILE" .key)
# Add the domain's certFile and keyFile to the Traefik configuration
echo "TRAEFIK TLS FILE ADD $DOMAIN"
printf " # CERT FILE $DOMAIN\n" >> $FILE
printf " - certFile: |-\n" >> $FILE
sed -e 's/^/ /' "$CERT_DIR/$DOMAIN.pem" >> $FILE
printf " keyFile: |-\n" >> $FILE
sed -e 's/^/ /' "$KEY_FILE" >> $FILE
printf "\n\n\n" >> $FILE
done
echo "Traefik dynamic configuration file created at $FILE"