How to Configure an Apache Reverse Proxy?

Configuring an Apache HTTP Server as a reverse proxy allows you to forward incoming client requests to a backend server, such as a Node.js, Python, or Tomcat application. This setup enhances security, enables load balancing, and centralizes SSL termination. By utilizing Apache’s mod_proxy core module along with its specific protocol extensions, administrators can seamlessly route traffic while masking the identity and structure of internal backend servers.

Prerequisites and Required Modules

Before initiating the configuration, you must ensure that the necessary proxy modules are enabled within your Apache installation. On Debian and Ubuntu-based systems, these modules can be activated using the a2enmod command, while RHEL and CentOS systems typically have them enabled by default in the main configuration file.

The core modules required for standard HTTP reverse proxying include:

To enable these modules on Ubuntu or Debian, execute the following commands in your terminal:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo systemctl restart apache2

Basic Reverse Proxy Configuration

To route incoming traffic from your Apache server to a backend application running locally (for example, on port 3000), you need to modify your virtual host configuration file. This file is typically located in /etc/apache2/sites-available/ on Debian/Ubuntu or /etc/httpd/conf.d/ on RHEL/CentOS.

Open your virtual host configuration file and insert the ProxyPass and ProxyPassReverse directives within the <VirtualHost> block:

<VirtualHost *:80>
    ServerName yourdomain.com

    ProxyPreserveHost On

    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/

    ErrorLog ${APACHE_LOG_DIR}/proxy-error.log
    CustomLog ${APACHE_LOG_DIR}/proxy-access.log combined
</VirtualHost>

Key Directives Explained

ProxyPreserveHost

Setting ProxyPreserveHost On instructs Apache to pass the original Host header from the client request to the backend server. This is critical if your backend application relies on the domain name to serve specific content or handle routing.

ProxyPass

The ProxyPass directive maps the remote server to the local server URL space. In the example above, ProxyPass / http://127.0.0.1:3000/ specifies that all requests incoming to the root URL (/) should be forwarded to the backend application running at http://127.0.0.1:3000/.

ProxyPassReverse

The ProxyPassReverse directive is crucial because it adjusts the headers in HTTP redirect responses sent by the backend server. If the backend application issues a redirect to an internal IP address, Apache intercepts the header and rewrites it to match your public domain name, preventing the client from attempting to connect to an unreachable internal address.

Managing Subdirectory Proxying

If you do not want to proxy the entire domain, you can target specific subdirectories or application paths. This approach is useful when Apache serves static website content from the root directory but needs to route specific API traffic to an application server.

<VirtualHost *:80>
    ServerName yourdomain.com
    DocumentRoot /var/www/html

    ProxyPass /api http://127.0.0.1:3000/api
    ProxyPassReverse /api http://127.0.0.1:3000/api
</VirtualHost>

In this scenario, requests to yourdomain.com/index.html are handled by the local document root, while any requests directed to yourdomain.com/api are securely routed to the backend service.

Testing and Applying Changes

Whenever changes are made to Apache configuration files, it is vital to test the syntax before restarting the service to avoid unexpected downtime.

Run the syntax check command:

sudo apachectl configtest

If the output displays Syntax OK, apply the new configuration by restarting the Apache service:

sudo systemctl restart apache2