Reverse-proxying web applications with Apache 2.4+
Note: Making a reverse proxy with nginx is much more straightforward.
A reverse proxy is a "man in the middle" server that tunnels requests to another server. You can use for things like:
- Expose a local service that you cannot directly reach over the internet
- "Change" the domain or path of a web application by rewriting them on the fly
- Instantly change servers that respond to a name or IP, without relying on DNS TTL
The following describes various Apache 2.4+ VHost directives to reverse-proxy an application that does not want to be reverse-proxied. The example we'll use is a proxy that responds to
http://public-host/public-path and secretly tunnels all requests to
For this to work you need the following Apache modules:
The basic VHost setup looks like this:
<VirtualHost *:80> ServerName public-host ProxyPass /public-path/ http://internal-host/internal-path/ ProxyPassReverse /public-path/ /private-path/ </VirtualHost>
In the block above,
ProxyPass will setup the reverse proxy.
ProxyPassReverse will make Apache rewrite 302 redirects like
Location: /private-path/foo to
If the internal server is on HTTPS
If you're tunneling to a server that's on HTTPs, you need to use
ProxyPass /public-path/ https://internal-host/internal-path/ SSLProxyEngine on
Note that it doesn't make your proxy available over
https://, it just makes sure that it can fetch from HTTPS internally. You've basically built your custom SSL-stripping MITM attack server.
If your proxy server should be accessible over HTTPS, use your regular Apache directives (
SSLEngine and friends) for this.
If the internal web app is hard-wiring cookie paths or domains, you need to rewrite those.
You can do this with the following directives:
ProxyPassReverseCookiePath /internal-path/ /public-path/ ProxyPassReverseCookieDomain internal-domain public-domain
Rewriting asset paths
If you are changing paths (
/public-path/foo) /while proxying, the proxied app will probably be broken:
- all absolute paths in your HTML's link
hrefs point to the wrong URL
- any CSS that contains directives like
background-image: url(/internal-path/wallpaper.png)will be break
The solution to this involves grepping and replacing all proxied text content. You also need to disable compression so you can find/replace text in the response. All of this is a little screwed up and might have unintended side effects, so make sure you really, absolutely, positively need to change the path while reverse-proxying. If you have control over the internal web application, prefer to deploy it to the same path that you expose publicly.
So anyway, here goes nothing:
Note that code above isn't aware of HTML or CSS in any way, it does a brute find-and-replace. You can now no longer use the string
/internal-path/ anywhere in your views.
Also note that the
FilterProvider syntax has changed in recent Apache versions, so make sure your Apache version (
apache2ctl -v) is 2.4 or higher.