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
sudoaccess - 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.