I'm configuring apache to proxy SSL requests to a local backend server. Here are the relevant parts of the virtual host:
<VirtualHost *:443>
...
SSLEngine on
SSLCertificateFile /path/to/server.crt
SSLCertificateKeyFile /path/to/server.key
RewriteEngine On
<Proxy balancer://unicornservers>
BalancerMember http://127.0.0.1:8080
</Proxy>
# Redirect all non-static requests to unicorn
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://unicornservers%{REQUEST_URI} [P,QSA,L]
ProxyPassReverse / balancer://unicornservers/
ProxyPreserveHost on
...
</VirtualHost>
When I use curl to access the server (curl -vk https://example.com
), the backend server performs a redirect to /login
, as it is supposed to.
The problem is, apache is not rewriting the Location
header properly. It returns a location of http://example.com/login
instead of https://example.com/login
.
Is there somewhere in my config where I need to tell apache to use https
for the ProxyPassReverse
rewrite?
Turns out I had improperly diagnosed this. The backend webserver (in this case, it happened to be rails) was actually specifying the http
URL explicitly. This is because it was using the incoming request parameters to build its redirection URL. So, since ProxyPreserveHost
was enabled, it was getting the host right, but not the protocol.
To fix it, I added the following line to my apache config:
RequestHeader set X-Forwarded-Proto "https"
This way, the backend rails server knows that the original request was over SSL, and it generates the redirection URL properly.