All we need is an easy explanation of the problem, so here it is.
Here is my situation:
- Server A:
support.example.com-> port 80 is forwarded to this server
- Server B:
Both are running apache2.
For server B I want to use Let’s encrypt. I want to redirect all HTTP requests to HTTPS except for location
./well-known/acme-challenge in order to be able to renew certificate.
Here is my virtualhost of server A:
<VirtualHost *:80> ServerName hr.example.com Redirect / https://hr.example.com RewriteEngine on RewriteRule ^"/.well-known/acme-challenge\$" "<IP-SERVER B>/.well-known/acme-challenge" [PT] </VirtualHost>
But this results in requests to
http://hr.example.com/.well-known/acme-challenge being redirect to HTTPS indeed.
How can I make an exception?
How to solve :
I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.
The Acme Challenge protocol that the LetsEncrypt bot uses will happily follow redirects. There is no need to reverse proxy the requests to another machine, you can simply redirect those requests there.
I would first create a specific redirect for the challenge and then redirect everything else to HTTPS:
<VirtualHost *:80> ServerName hr.example.com Redirect permanent /.well-known/acme-challenge/ http://support.example.com/.well-known/acme-challenge/ Redirect permanent / https://hr.example.com/ </VirtualHost>
I just tested this set of rules on my server by creating this virtual host and putting
hr.example.com into my
/etc/hosts file as
# curl -s --head http://hr.example.com/ HTTP/1.1 301 Moved Permanently Location: https://hr.example.com/ # curl -s --head http://hr.example.com/.well-known/acme-challenge/foo HTTP/1.1 301 Moved Permanently Location: http://support.example.com/.well-known/acme-challenge/foo
It is often problematic to mix rewrite rules and redirect directives. It isn’t always clear which will be executed first. If you do want to use the proxy method, I would switch your redirect to a rewrite rule that follows the proxy directive. I changed your rewrite rule a bit too. It should be a proxy rule (
[P]) not a pass-through rule (
[PT]). You also need to proxy every file within that challenge directory, not just the directory itself.
<VirtualHost *:80> ServerName hr.example.com RewriteEngine on RewriteRule ^/.well-known/acme-challenge/(.*) http://<IP-SERVER B>/.well-known/acme-challenge/$1 [P,L] ProxyPassReverse /.well-known/acme-challenge/ http://<IP-SERVER B>/.well-known/acme-challenge/ RewriteRule /(.*) https://hr.example.com/$1 [R=301,L] </VirtualHost>
I blogged about similar problems that I had. A trick that I found helpful but which doesn’t appear to exactly match your situation was to create an exception to proxy rules. If you are reverse proxying your entire site but you want to make an exception to handle the acme challenge locally (or allow it to be redirected) you can prevent the proxying of that directory with:
# Don't allow this directory to be reverse proxied ProxyPass /.well-known/acme-challenge/ !
Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂