Apache’s mod_proxy module turns your existing Apache web server into a fully functional reverse proxy without requiring a second web server like Nginx. This is particularly useful when you already have Apache managing SSL termination, virtual hosts, or authentication, and want to forward traffic to a backend application server such as Tomcat, Node.js, or a microservice listening on a local port. On RHEL 8, setting up Apache as a reverse proxy requires enabling the correct proxy modules, writing the appropriate configuration directives, and allowing outbound network connections through SELinux.

Prerequisites

  • A RHEL 8 server with sudo access
  • Apache (httpd) installed and running
  • A backend application listening on a local port (e.g., localhost:8080)
  • Port 80 (and optionally 443) open in firewalld
  • SELinux enforcing mode (default on RHEL 8)

Step 1 — Verify Proxy Modules Are Loaded

Apache on RHEL 8 ships with the proxy modules available but not always enabled. Check which proxy-related modules are currently loaded, then enable mod_proxy and mod_proxy_http if they are not already active.

httpd -M | grep proxy

You should see output similar to:

proxy_module (shared)
proxy_http_module (shared)

If the modules are not listed, load them by editing the main configuration or adding a LoadModule file:

echo "LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so" | sudo tee /etc/httpd/conf.modules.d/00-proxy-extra.conf
sudo systemctl restart httpd

Step 2 — Create a Reverse Proxy Virtual Host Configuration

Create a dedicated configuration file for your reverse proxy virtual host. The ProxyPass and ProxyPassReverse directives do the core forwarding work, while ProxyPreserveHost On ensures the original Host header is forwarded to the backend rather than being replaced with the proxy server’s hostname.

sudo nano /etc/httpd/conf.d/myapp-proxy.conf

Add the following virtual host block:


    ServerName example.com
    ServerAlias www.example.com

    ProxyPreserveHost On
    ProxyPass        / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/

    ErrorLog  /var/log/httpd/myapp-error.log
    CustomLog /var/log/httpd/myapp-access.log combined

ProxyPassReverse rewrites the Location, Content-Location, and URI headers in responses from the backend, ensuring that redirects issued by the backend application point to the correct public URL rather than the internal localhost:8080 address.

Step 3 — Test the Configuration and Restart Apache

Always validate the Apache configuration syntax before reloading to avoid taking the server offline with a typo.

sudo apachectl configtest
sudo systemctl reload httpd

A successful test returns Syntax OK. If there are errors, review the output carefully and correct the configuration file before proceeding.

Step 4 — Allow Backend Connections Through SELinux

On RHEL 8, SELinux enforcing mode blocks Apache from initiating network connections to backend services by default. This is a common source of 503 Service Unavailable errors that appear even when the proxy configuration is correct. Enable the httpd_can_network_connect boolean to grant the necessary permission.

sudo setsebool -P httpd_can_network_connect 1
getsebool httpd_can_network_connect

If your backend is a database listening on a non-standard port, you may also need httpd_can_network_connect_db. Review the SELinux audit log if you still encounter denials:

sudo ausearch -m avc -ts recent | grep httpd

Step 5 — Configure Proxy Timeout Directives

For backend applications that may take longer to respond — such as those performing complex database queries or file processing — increase the proxy timeout values to prevent Apache from returning 504 Gateway Timeout responses to clients before the backend has finished.


    ServerName example.com

    ProxyPreserveHost On
    ProxyPass        / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/

    ProxyTimeout         120
    Timeout              120
    KeepAliveTimeout     15
    MaxKeepAliveRequests 100
sudo apachectl configtest && sudo systemctl reload httpd

Step 6 — Verify the Reverse Proxy Is Working

Send a test request to confirm that Apache is correctly forwarding traffic to your backend and that responses are returned through the proxy.

curl -I http://example.com
curl -v http://example.com 2>&1 | grep -E "< HTTP|< Server|< X-"

Check the Apache access and error logs for any issues:

sudo tail -f /var/log/httpd/myapp-access.log
sudo tail -f /var/log/httpd/myapp-error.log

Conclusion

Apache’s mod_proxy and mod_proxy_http modules are now configured to reverse proxy all requests on your RHEL 8 server to a backend application on localhost:8080. The SELinux boolean adjustment is a critical and often-overlooked step specific to RHEL and its derivatives, and the timeout configuration ensures your proxy remains stable under real-world workloads. With ProxyPreserveHost On and ProxyPassReverse in place, your backend application receives accurate request context and its redirects resolve correctly.

Next steps: How to Secure Apache with Let’s Encrypt and Certbot on RHEL 8, How to Enable HTTP/2 with Apache on RHEL 8, and How to Configure Apache Virtual Hosts on RHEL 8.