How to Forward Client IP from HAProxy to Apache2

3 min read

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:

  1. HAProxy adds the real client IP to the X-Forwarded-For header before forwarding the request
  2. Apache reads that header and uses it as the client IP instead of the connection source

Prerequisites

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 the X-Forwarded-For header with the client’s IP to every request
  • http-request set-header X-Real-IP %[src] — sets a separate X-Real-IP header 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 IP
  • RemoteIPTrustedProxy 10.0.1.5 — the IP address of your HAProxy server. Apache only trusts this header when the request comes from this IP. Replace 10.0.1.5 with 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 by mod_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
How to Forward Client IP from HAProxy to 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.

How to Forward Client IP from HAProxy to Apache2

Troubleshooting

  • Still seeing HAProxy’s IP? — Check that you changed %h to %a in the LogFormat. This is the most common miss.
  • mod_remoteip not loading? — Confirm with sudo apachectl -M | grep remoteip. You should see remoteip_module in the output.
  • IP shows as the wrong address? — Make sure RemoteIPTrustedProxy matches 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 forwardfor only works when both frontend and backend use mode 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.