Understanding and Implementing Apache’s ProxyPassReverse Directive for Reverse Proxy Scenarios


2 views

The ProxyPassReverse directive serves as a critical component in Apache's reverse proxy configuration. When your backend server issues HTTP redirects (3xx responses), this directive modifies the Location, Content-Location, and URI headers in the response to maintain the reverse proxy facade.

Consider this common scenario without ProxyPassReverse:


# Backend server responds with:
HTTP/1.1 302 Found
Location: http://backend.internal/app/newpath

Without modification, the client would receive this redirect and attempt to connect directly to backend.internal, bypassing your proxy entirely.

Here's a complete reverse proxy setup with ProxyPassReverse:


<VirtualHost *:80>
    ServerName proxy.example.com
    
    ProxyPass /app/ http://backend.internal:8080/
    ProxyPassReverse /app/ http://backend.internal:8080/
    
    # Additional reverse proxy settings
    ProxyPreserveHost On
    RequestHeader set X-Forwarded-Proto "http"
</VirtualHost>

For complex environments with multiple backend paths:


ProxyPass /service1/ http://backend1.internal:8000/
ProxyPassReverse /service1/ http://backend1.internal:8000/

ProxyPass /service2/ http://backend2.internal:9000/
ProxyPassReverse /service2/ http://backend2.internal:9000/

Problem: Redirects still bypass the proxy
Solution: Ensure the ProxyPassReverse path matches exactly with ProxyPass

Problem: HTTPS redirects break
Solution: Add protocol-aware configuration:


ProxyPassReverse / https://backend.internal/
ProxyPassReverse / http://backend.internal/

For complete URL rewriting in HTML content:


ProxyHTMLEnable On
ProxyHTMLURLMap http://backend.internal/ /

Enable detailed logging to troubleshoot redirect issues:


LogLevel debug
CustomLog ${APACHE_LOG_DIR}/proxy.log "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""

When implementing reverse proxy configurations in Apache, backend servers often issue HTTP redirects (301/302 responses) containing backend-specific URLs in Location headers. Without proper handling, these redirects would expose internal server structures and potentially bypass the proxy entirely.


# Problematic scenario without ProxyPassReverse
ProxyPass "/app/" "http://backend-server:8080/internal-app/"

If the backend issues a redirect to "/internal-app/dashboard", clients receive this raw internal URL, breaking the reverse proxy abstraction.

The directive modifies three response headers:

  • Location (HTTP redirects)
  • Content-Location (resource identifiers)
  • URI (rarely used header)

It performs string substitution based on the same path mapping rules as ProxyPass:


# Basic configuration example
ProxyPass "/public/app/" "http://internal-server:8000/"
ProxyPassReverse "/public/app/" "http://internal-server:8000/"

Simple Single-Server Setup


<VirtualHost *:443>
    ServerName public.example.com
    
    ProxyPass "/api/" "http://10.0.1.42:3000/"
    ProxyPassReverse "/api/" "http://10.0.1.42:3000/"
    
    # Required for WebSocket support
    ProxyPass "/ws/" "ws://10.0.1.42:3001/" 
    ProxyPassReverse "/ws/" "ws://10.0.1.42:3001/"
</VirtualHost>

Complex Path Rewriting Scenario


# When backend paths differ from frontend
ProxyPass "/customer-portal/v2/" "http://backend/v3/portal/"
ProxyPassReverse "/customer-portal/v2/" "http://backend/v3/portal/"

# Additional configuration for cookies if needed
ProxyPassReverseCookiePath "/v3/portal/" "/customer-portal/v2/"

Multiple Backend Servers

For load-balanced setups, ensure ProxyPassReverse matches all possible backend URLs:


<Proxy balancer://app-cluster>
    BalancerMember http://backend1:8080
    BalancerMember http://backend2:8080
</Proxy>

ProxyPass "/app/" "balancer://app-cluster/"
ProxyPassReverse "/app/" "http://backend1:8080/"
ProxyPassReverse "/app/" "http://backend2:8080/"

SSL Termination Cases

When the proxy handles HTTPS but communicates with backends via HTTP:


ProxyPass "/" "http://backend/"
ProxyPassReverse "/" "http://backend/"
ProxyPassReverse "/" "https://public-domain.com/"

Using Regular Expressions


# Apache 2.4+ syntax
ProxyPassMatch "^/(.*)-service/(.*)" "http://backend/$1/$2"
ProxyPassReverse "/user-service/" "http://backend/user/"
ProxyPassReverse "/order-service/" "http://backend/order/"

Combining with Other Modules

For complete URL rewriting including HTML content:


# Requires mod_proxy_html
ProxyHTMLEnable On
ProxyHTMLURLMap http://backend/ /

Diagnostic steps:

  1. Enable mod_headers to inspect raw responses: Header always set X-Proxy-Debug "enabled"
  2. Check Apache error logs with LogLevel debug
  3. Use curl with -v flag to examine headers: curl -v https://proxy/app/redirect-endpoint