Let’s Encrypt and Certbot make issuing and renewing TLS certificates easy — until your servers sit behind a load balancer like HAProxy, NGINX, or Traefik. Suddenly, what used to be a simple certbot renew
becomes a frustrating challenge.

You might run into issues like:
- HTTP-01 challenges being blocked or misrouted by your reverse proxy
- HTTPS redirects interfering with challenge resolution
- ACME validation paths not reaching the correct backend
- DNS-01 failing because your DNS provider doesn’t support ACME automation
Result: You can’t re-issue your certificate — or only with brittle, manual workarounds.
Why ACME Challenges Fail Behind Load Balancers
Let’s Encrypt uses ACME challenges to verify domain ownership. In practice, that’s often one of two methods:
🔸 HTTP-01 (via /.well-known/acme-challenge/
)
This method fails when:
- The load balancer terminates SSL and doesn’t forward HTTP paths
- HTTPS redirection breaks the challenge
- The app server never receives the request
🔸 DNS-01 (via TXT records)
This is more reliable, if:
- Your DNS provider supports API automation
- You have full control over DNS (often not the case in enterprise)
In short: if ACME validation fails, you’re stuck — unless you can transfer an already-valid certificate.
The Simple Alternative: Transfer the Certificates Directly
Instead of reissuing a new cert, you can securely copy existing Let’s Encrypt certificates from one server to another. This is especially useful when:
- Migrating from an old VPS or container
- Spinning up a new staging or backup instance
- Your domain is behind a reverse proxy or load balancer
- DNS-based challenges are not possible to automate
No ACME involved. No renewal issues. Just copy what already works.
Use the Ready-Made Script
To simplify the transfer, I’ve published a small Bash script on GitHub:
What the Script Does:
- Transfers all essential Let’s Encrypt files using
rsync
over SSH:/etc/letsencrypt/live/
/etc/letsencrypt/archive/
/etc/letsencrypt/renewal/
- Preserves folder structure, permissions, and symbolic links
- Can optionally reload your web server (e.g.
nginx
,apache
) after import
The goal: allow the target server to continue using the certificate without revalidation — including future certbot renew
operations.
How to use
- Download the script
cd /root && git clone https://github.com/filipnet/letsencrypt-transfer.git
- Use the script by its input parameters in e.g.
/etc/crontab
- Or create a “helper-script” to do some more actions
vim /root/letsencrypt-transfer/transfer-certs-lb.sh
Sample Helper Script
echo "Starting LetsEncrypt certificate transfer"
# LetsEncrypt Archive
/root/letsencrypt-transfer/letsencrypt-transfer-certs.sh lb.domain.de /etc/letsencrypt/archive/lb.domain.de/ /etc/letsencrypt/archive/lb.domain.de/ /root/rsa-key/id_rsa_lb.domain.de.pem
# LetsEncrypt Live (Notice that the live-folder only use SYMLINKS)
/root/letsencrypt-transfer/letsencrypt-transfer-certs.sh lb.domain.de /etc/letsencrypt/live/lb.domain.de/ /etc/letsencrypt/live/lb.domain.de/ /root/rsa-key/id_rsa_lb.domain.de.pem
echo "Restart Apache"
apachectl graceful
echo "Restart Dovecot"
systemctl reload dovecot
echo "Restart Postfix"
systemctl reload postfix
Security Considerations
- The archive contains private keys. Use secure SSH channels only.
- Don’t share or store the archive permanently.
Final Thoughts
Behind a proxy or load balancer, Let’s Encrypt renewal can easily break — especially if ACME challenges aren’t reliably passed through. Rather than fight the config or depend on DNS APIs you don’t control, you can transfer the certificate directly.
It’s simple, safe, and scriptable — and lets you keep your infrastructure running smoothly without risking downtime or validation errors.