Apache virtual hosts and reverse proxy
I have many virtual hosts whose domain names map to a single Apache server (let's call it server1). Under certain circumstances, all URLs for a certain virtual host should be served by a different server instead (let's call it server2).
What's the easiest way to accomplish that? Can I simply set server2 to use the same name-based virtual host setup as server1, and then rely on server1's X-Forwarded-Host headers (i.e. will server2 do the right thing based on just those header's)? By "same name-based virtual host setup" I mean the "real" domain names (i.e. the domain names which map to server1's IP).
Solution 1:
you can indeed use the mod_proxy module. It runs fine with vhosts. Basically, the main server will receive all the requests, and when a certain url/domain is called, mod_proxy will redirect this domain to another server (server 2) it looks like this on server 1
<VirtualHost *>
ServerName server1.com
Hosted on the server
</VirtualHost *>
<VirtualHost *>
ServerName server2.com
// mod_proxy directives in order to redirect this domain name to the other server //
</VirtualHost>
And there is a good tutorial : http://www.apachetutor.org/admin/reverseproxies
Solution 2:
I just run into the same problem, I've explored two solutions:
-
Mirror the external hierarchy on the internal DNS (e.g. foo.example.com -> foo.internal.lan, bar.example.com -> bar.internal.lan, etc.); in each
VirtualHost
block in the frontend you add the appropriateProxyPass
andProxyPassReverse
directives. If you have vhosts then you can create a catch-all (ServerAlias *.example.com
) section in the frontend and use mod_rewrite ([P]
) to proxy the request to the backend, mapping the requests to the internal names.This the first approached that I tried: it works fine, but requires changes in the naming of the backend. If you can't touch the DNS or if the backend server doesn't even have a name than you cannot use this approach.
Oh, don't forget to fixup the cookies with
ProxyPassReverseCookieDomain
, otherwise you'll stare at the logs wondering why sessions don't work anymore ;-) Use a catch-all vhost in the frontend, and use
ProxyPreserveHost on
; in this case the frontend preserves the Host: header in the request, so you can reuse your original vhost configuration in the backend (i.e. the backend sees request with the external name in the header Host: foo.example.com)