Troubleshooting & How-Tos

Redirecting HTTPS with Let’s Encrypt and Apache

The free TLS certificate provider Let’s Encrypt automates the request-and-setup process using the ACME protocol to verify domain ownership. Software on your server creates a file in a known location, based on your request. The certificate authority checks that location, and if it finds a match to your request, it will grant the certificate. (You can also validate it using a DNS record, but not all implementations provide that. DreamHost, for instance, only uses the file-on-your-server method.)

That makes it really simple for a site that you want to run over HTTPS.

Redirected sites are trickier. If you redirect all traffic from Site A to Site B, Let’s Encrypt won’t find A’s keys on B, so it won’t issue (or renew!) the cert. You need to make an exception for that path.

On the Let’s Encrypt forums, jmorahan suggests this for Apache:

RedirectMatch 301 ^(?!/\.well-known/acme-challenge/).* https://example.com$0

That didn’t quite work for me since I wanted a bit more customization. So I used mod_rewrite instead. My rules are a little more complicated (see below), but the relevant part boils down to this:

RewriteEngine On
RewriteBase /

# Redirect all hits except Let's Encrypt ACME Challenge to example.com
RewriteCond %{REQUEST_URI} !^.well-known/acme-challenge
RewriteRule ^(.*) https://example.com/$1 [R=301,L]

These rules can go in your server config file if you run your own server, or the .htaccess for the domain if you don’t.

The reason I went with the more complex mod_rewrite solution is that I hadn’t finished updating the entire target site to work over HTTPS. Some sections still had absolute links or remote embeds that needed to be updated. So rather than always redirecting to the HTTPS site, I wanted to set up the redirecting domain to preserve whichever scheme was used to access it. So my redirect rules look like this:

RewriteEngine On
RewriteBase /

# Redirect all hits except Let's Encrypt ACME Challenge to example.com
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} !^.well-known/acme-challenge
RewriteRule ^(.*) http://example.com/$1 [R=301,L]

RewriteCond %{REQUEST_URI} !^.well-known/acme-challenge
RewriteRule ^(.*) https://example.com/$1 [R=301,L]

Comments

Jakub Pinkas

Hi,

thanks for idea how to do this. I found on Debian Apache2.4 at least there has to be change from:
RewriteCond %{REQUEST_URI} !^.well-known/acme-challenge
to:
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge

The init “/” for URI Request

Bencho Naut

How we did it

RedirectMatch 301 ^(?!/\.well-known/acme-challenge/).* https://domain.tld$0

😉