X
Popular Searches

How to Set Up a Reverse Proxy With Apache

 

Photo of the Apache web server logo on a computer screen
Sharaf Maksumov/Shutterstock.com

Apache is a versatile web server which offers a full complement of supporting features, some of them via extensions. In this article, we’ll use the mod_proxy module to configure Apache in a reverse proxy role.

While Apache might not be your first choice as a reverse proxy, with more modern alternatives like NGINX tending to steal attention, mod_proxy is useful for servers which are already running Apache and now need to route traffic to another service. You can set up an Apache virtual host to pass on requests for a given domain to a separate web server.

We’re using Apache 2.4 with a Debian-based system for the purposes of this guide. We’ll also assume the servers you want to proxy traffic to are already network-accessible from your Apache host. This article focuses on enabling proxying based on a unique virtual host but mod_proxy is also configurable globally, as part of your Apache server config, or at the directory-level via .htaccess files.

Enabling The Proxy Module

mod_proxy is included with the default Apache installation. Use a2enmod to activate the module and its independent HTTP component now:

sudo a2enmod proxy
sudo a2enmod proxy_http

This sets up Apache to support proxying HTTP connections to other hosts. The module is configured using Proxy-prefixed instructions in your Apache config files. We’ll set these up next.

Setting Up a Proxied Virtual Host

Let’s set up a virtual host that forwards example.com to the internal IP address 192.168.0.1. You should add a DNS record for example.com that points to your Apache host.

Advertisement

Proxying in this scenario lets visitors transparently access your internal web server via an external address. Apache is acting as the gatekeeper that routes traffic to its final destination. The user will see example.com, even though Apache actually resolves requests via the separate server.

Add a new virtual host file inside /etc/apache2/sites-available with the following content:

<VirtualHost *:80>
    ServerName example.com

    ProxyPass / http://192.168.0.1/ nocanon
    ProxyPassReverse / http://192.168.0.1/
</VirtualHost>

The ProxyPass and ProxyPassReverse directives specify that traffic to example.com should be proxied to 192.168.0.1. The optional nocanon keyword instructs Apache to pass the raw URL to the remote server. Without this keyword, Apache will automatically canonicalize the URL, which can be incompatible with some servers and frameworks. Using nocanon guarantees compatibility but can affect your security posture as it disables Apache’s built-in protection against URL-based proxy attacks.

ProxyPassReverse must be provided to distinguish your configuration as a reverse proxy setup. Apache will use the provided URL to rewrite Location, Content-Location, and URI response headers issued by your backend. This ensures subsequent requests continue to hit the reverse proxy, instead of trying to reach the internal server directly.

This configuration will proxy all requests. You can restrict proxying to a specific path such as /media by adjusting the ProxyPass and ProxyPassReverse instructions:

ProxyPass /media http://192.168.0.1/
ProxyPassReverse /media http://192.168.0.1/
Advertisement

Adding multiple ProxyPass rules lets you route requests between several targets using one virtual host. Rules are matched in the order they’re written. If you need more complex routing behavior, use the ProxyPassMatch directive instead. This is equivalent to ProxyPass but matches incoming URLs against a regular expression:

ProxyPassMatch ^/client/(.*)/images$ http://192.168.0.1/

Save your virtual host file and enable it using the a2ensite command. This takes the basename of your file, relative to the sites-available directory:

sudo a2ensite example-proxy-vhost

Restart Apache to apply your changes:

sudo service apache2 restart

Your simple proxy should now be operational. Try visiting example.com – you should see the content served by 192.168.0.1. The request terminates at your Apache host which then proxies it to your internal server.

Using SSL

The above example omits SSL. In a production workload, you’d want to set this up by adding SSLCertificateFile and SSLCertificateKeyFile settings to your virtual host. These specify the SSL certificate and key to use when validating SSL connections. You could also use Let’s Encrypt’s certbot to automate set up.

Configuring SSL in this way means the secure connection will be terminated at your Apache host. The connection between Apache and your proxy target will be made over plain HTTP.

If you need the proxy connection to be secured too, you must use the SSLProxy options provided by mod_ssl. SSLProxyEngine = On will work as the most basic config, provided both Apache and your proxy target server have access to the same certificates. This option instructs SSL information to be fed over the proxied connection.

Proxy Options

Apache reverse proxies have several optional directives you can use to adjust forwarding behavior. Here are some commonly used options:

  • ProxyAddHeaders – Apache passes X-Forwarded-Host, XForwarded-For, and X-Forwarded-Server headers to your backend server by default. These let your backend identify that a request was proxied via Apache. Setting this header to Off prevents Apache from adding these headers.
  • ProxyErrorOverride – Apache won’t interfere with responses sent by your backend server unless instructed to. If your backend serves a 400, 404, 500, or any other error code, the user will receive that content as-is. Setting ProxyErrorOverride changes this, letting Apache replace the content of error pages with the configured ErrorDocument instead. This can be desirable in situations where you want errors from all your backends to be handled uniformly with configuration centralized on the proxy host.
  • ProxyPassReverseCookieDomain – This functions similarly to the mandatory (for reverse proxying) ProxyPassReverse directive. It will rewrite the domain in Set-Cookie headers to reference the virtual host’s name, rather than the hostname of the backend server they originate from.
  • ProxyPreserveHost – Apache usually sends its own hostname to your backend servers as the value of the Host header. Setting this directive means the original Host header will be sent instead. This may be necessary when your backend software performs its own hostname-based routing.
  • ProxyTimeout – Use this directive to adjust the time Apache will wait while your backend server processes a proxied request. Apache will abort the request and return an error code to the client if the timeout is exceeded. It defaults to the server-level Timeout value.
Advertisement

You can set these directives as additional lines in your virtual host file. Remember to restart the Apache service each time you apply a change.

Load Balancing

Apache’s reverse proxy implementation also supports load balancing between multiple different backends. This lets a request to example.com hit any of the servers in your balancing pool.

<Proxy balancer://example-balancer>
    BalancerMember http://192.168.0.1
    BalancerMember http://192.168.0.2
    ProxySet lbmethod=bytraffic
</Proxy>

ProxyPass / balancer://example-balancer
ProxyPassReverse / balancer://example-balancer

This example routes requests to one of two servers in the example-balancer pool. The load balancing algorithm is defined by the lbmethod setting; the bytraffic value used here tries to ensure each of the servers handle an equal amount of traffic.

The alternative  byrequests balancing method is a simpler version of bytraffic that gives each backend an equal share of the incoming requests. The  bybusyness balancer tracks how many requests each backend is serving, then assigns new ones to the least “busy” backend.

Summary

The mod_proxy module can turn Apache into a reverse proxy host that lets you use name-based routing to access multiple independent services. You can add load balancing too to ensure stability and uptime by distributing requests across your server fleet.

Advertisement

Other proxy flavors are available too. You can proxy FTP, WebSocket, and HTTP2 connections, among others, by installing additional addons alongside mod_proxy. The full list of modules is available in the Apache docs.

James Walker James Walker
James Walker is a CloudSavvy IT contributor. He's the Founder of Heron Web where he provides bespoke software development services to SMEs, specializing in web applications and APIs. He's experienced with the complete development lifecycle and works with DevOps technologies such as GitLab, Docker, and Kubernetes. Read Full Bio »

The above article may contain affiliate links, which help support CloudSavvy IT.