When working with IIS servers configured for virtual hosting (where multiple sites share the same IP and port), HAProxy must preserve or modify the Host header to ensure requests reach the correct backend application. Unlike simpler setups where backends have dedicated ports, IIS relies heavily on host headers for routing.
The key is to dynamically set the Host header based on which backend server is selected. Here's a complete configuration example:
frontend http-in
bind *:80
mode http
acl is_node1 hdr(host) -i node1.myapp.mycompany.com
acl is_node2 hdr(host) -i node2.myapp.mycompany.com
use_backend node1_servers if is_node1
use_backend node2_servers if is_node2
default_backend nodes
backend node1_servers
mode http
server web01 node1.myapp.mycompany.com:80 check
http-request set-header Host node1.myapp.mycompany.com
backend node2_servers
mode http
server web02 node2.myapp.mycompany.com:80 check
http-request set-header Host node2.myapp.mycompany.com
backend nodes
mode http
balance roundrobin
option forwardfor
http-request set-header Host myapp.mycompany.com
server web01 node1.myapp.mycompany.com:80 check
server web02 node2.myapp.mycompany.com:80 check
For health checks to work properly with IIS virtual hosts, we need to configure them with the correct Host headers:
option httpchk GET /healthcheck HTTP/1.1\r\nHost:\ node1.myapp.mycompany.com
http-check expect status 200
For larger deployments, consider using HAProxy maps for dynamic host header assignment:
frontend http-in
bind *:80
mode http
use_backend %[req.hdr(host),lower,map(/etc/haproxy/host_backend.map,nodes)]
backend nodes
mode http
http-request set-header Host %[req.hdr(host),lower,map(/etc/haproxy/host_header.map,myapp.mycompany.com)]
Sample map file contents:
# host_backend.map
node1.myapp.mycompany.com node1_servers
node2.myapp.mycompany.com node2_servers
- Enable HAProxy logging with
option httplog
to verify headers - Use
curl -v
to inspect request headers - Test with
set-server-ssl
if using HTTPS backends
When working with IIS servers that use host headers for virtual hosting, HAProxy configurations require special attention to properly forward requests. The core issue emerges when multiple backend nodes need distinct host headers while serving the same frontend domain.
In our infrastructure, we have:
Frontend: myapp.mycompany.com → HAProxy
Backends:
- node1.myapp.mycompany.com (IIS with host header binding)
- node2.myapp.mycompany.com (IIS with host header binding)
The initial HAProxy configuration fails because:
- Static host header rewriting affects all backend servers
- Health checks don't verify with proper host headers
Here's the proper configuration approach using HAProxy 1.7.9+:
frontend http-in
bind *:80
acl is_node1 hdr(host) -i myapp.mycompany.com
use_backend nodes if is_node1
backend nodes
mode http
balance roundrobin
option forwardfor
# Dynamic host header based on selected server
http-request set-header Host %[srv_name].myapp.mycompany.com
server web01 node1.myapp.mycompany.com:80 check
server web02 node2.myapp.mycompany.com:80 check
For more complex scenarios, consider these variations:
1. Using Server Templates
backend nodes
mode http
balance roundrobin
server-template web 2 node{}.myapp.mycompany.com:80 \
check resolvers dns1 init-addr none \
source 0.0.0.0 usesrc clientip \
ssl verify none
2. Separate Backends with ACLs
frontend http-in
bind *:80
acl is_node1 path_beg /api/v1
acl is_node2 path_beg /api/v2
use_backend node1_backend if is_node1
use_backend node2_backend if is_node2
backend node1_backend
server web01 node1.myapp.mycompany.com:80 check
http-request set-header Host node1.myapp.mycompany.com
backend node2_backend
server web02 node2.myapp.mycompany.com:80 check
http-request set-header Host node2.myapp.mycompany.com
Proper health checks require matching host headers:
option httpchk GET /health
http-check send hdr Host node1.myapp.mycompany.com
For dynamic health checks per server:
backend nodes
server web01 node1.myapp.mycompany.com:80 \
check send-proxy-v2 \
check-send-proxy hdr Host node1.myapp.mycompany.com
server web02 node2.myapp.mycompany.com:80 \
check send-proxy-v2 \
check-send-proxy hdr Host node2.myapp.mycompany.com
- Enable HAProxy debug logging with
option log-health-checks
- Verify headers using
curl -v -H "Host: myapp.mycompany.com" http://haproxy-ip/
- Check IIS logs for received host headers