When HAProxy sits in front of Apache2 as a reverse proxy, Apache logs the proxy’s IP address instead of the real client IP. This breaks access logs, geo-based rules, and rate limiting. This guide shows you how to forward the client IP from HAProxy to Apache2 using the X-Forwarded-For header and Apache’s mod_remoteip module.
How It Works
By default, Apache sees the TCP connection source — which is HAProxy, not the actual client. The fix has two parts:
- HAProxy adds the real client IP to the
X-Forwarded-Forheader before forwarding the request - Apache reads that header and uses it as the client IP instead of the connection source
Prerequisites
- HAProxy installed and running as a reverse proxy
- Apache2 installed on the backend server — see How to Install Apache 2.4 Web Server on EC2 Ubuntu 22.04 LTS if needed
- SSH access to both servers
Step 1: Configure HAProxy to Forward the Client IP
Edit your HAProxy configuration:
sudo nano /etc/haproxy/haproxy.cfg
In your backend section for Apache, add option forwardfor and the X-Real-IP header:
backend apache_backend
mode http
option forwardfor
http-request set-header X-Real-IP %[src]
server web1 10.0.1.10:80 check
option forwardfor— adds theX-Forwarded-Forheader with the client’s IP to every requesthttp-request set-header X-Real-IP %[src]— sets a separateX-Real-IPheader with the source IP (some apps expect this header specifically)%[src]— HAProxy variable that resolves to the client’s source IP address
Make sure your frontend section uses mode http as well. The option forwardfor directive only works in HTTP mode.
Validate and reload HAProxy:
sudo haproxy -c -f /etc/haproxy/haproxy.cfg && sudo systemctl reload haproxy
Step 2: Enable mod_remoteip on Apache
On the Apache backend server, enable the remoteip module:
sudo a2enmod remoteip
This module tells Apache to replace the connection IP with the value from a trusted header like X-Forwarded-For.
Step 3: Configure Apache to Trust HAProxy
Edit the main Apache config:
sudo nano /etc/apache2/apache2.conf
Add these directives:
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 10.0.1.5
RemoteIPHeader X-Forwarded-For— tells Apache which header contains the real client IPRemoteIPTrustedProxy 10.0.1.5— the IP address of your HAProxy server. Apache only trusts this header when the request comes from this IP. Replace10.0.1.5with your HAProxy server’s actual IP.
Step 4: Update the Apache Log Format
This step is often missed. By default, Apache’s LogFormat uses %h which logs the connection source (HAProxy). The mod_remoteip module populates %a instead, so you need to update your log format.
In the same apache2.conf, find the LogFormat lines and change %h to %a:
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%a %l %u %t \"%r\" %>s %O" common
%h— logs the TCP connection source (always HAProxy in a proxy setup)%a— logs the client IP as determined bymod_remoteip(the real client)
If you skip this step, your access logs will still show the HAProxy IP even though mod_remoteip is working correctly.
Step 5: Test and Restart Apache
Validate the configuration and restart:
sudo apache2ctl configtest && sudo systemctl restart apache2

Step 6: Verify the Client IP in Logs
Send a request through HAProxy to your Apache backend, then check the access log:
sudo tail -f /var/log/apache2/access.log
You should now see the actual client IP addresses instead of the HAProxy server’s IP.

Troubleshooting
- Still seeing HAProxy’s IP? — Check that you changed
%hto%ain the LogFormat. This is the most common miss. - mod_remoteip not loading? — Confirm with
sudo apachectl -M | grep remoteip. You should seeremoteip_modulein the output. - IP shows as the wrong address? — Make sure
RemoteIPTrustedProxymatches your HAProxy server’s IP exactly. If HAProxy connects from a different IP than you configured, Apache ignores the header. - HAProxy in TCP mode? —
option forwardforonly works when both frontend and backend usemode http. In TCP mode, use the PROXY protocol instead.
Conclusion
Your Apache access logs now show the real client IP instead of HAProxy’s address. This is essential for accurate traffic analysis, security auditing, and any application logic that depends on the client’s IP. If you need to secure your Apache server with SSL behind the proxy, see How to Secure Apache2 with Let’s Encrypt on Ubuntu 22.04. For monitoring your Apache setup, check out How to Install Datadog Agent with Apache2 on EC2 Ubuntu 22.04.

