HAProxy is an open source load balancer, capable of balancing any TCP based service. It’s commonly used for balancing HTTP, and can help solve traffic problems on your web server. Here’s how to set it up.

What Is HAProxy?

Load balancers like HAProxy allow you to split traffic over multiple servers, making it easier to handle. Instead of pointing your IP at your web server, you’d point it at an HAProxy server, which would decide where to send it from there. HAProxy is very lightweight, and doesn’t need a lot of resources to operate, so you can use a single load balancer for many backend servers. Ideally, you want both your HAProxy server and your web servers to be hosted in the same datacenter, from the same cloud provider, to cut down on latency.

HAProxy also allows your network to be more resilient. If one web server goes down, HAProxy can route traffic to the rest while you diagnose the issue. For it to be truly resilient, you’ll want to have a backup HAProxy server, in case your load balancer goes down.

Even with HAProxy, you’ll still often want a full site CDN in front of it, both to handle additional load and to have multiple points of presence closer to the end user.

How To Set Up HAProxy Load Balancing

First, install HAProxy from your distro’s package manager. For Debian based systems like Ubuntu, that would be:

apt-get install haproxy

Next, you’ll need to turn it on by editing the init script at /etc/default/haproxy and setting ENABLED to 1:


Now, if you run service haproxy, you should see that it is enabled and ready to be configured. We’ll start by archiving the default configuration file:

mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.old

Create a new config file in its place, and start by adding a few global settings:

    log local0 notice
    maxconn 2000
    user haproxy
    group haproxy
    stats enable
    stats uri /haproxy?stats
    stats realm HAProxy Statistics
    stats auth admin:password

The log setting specifies the syslog server that HAProxy sends logs to. You’ll need to have a server like rsyslog running to make use of this. The maxconn setting specifies the max concurrent connections, and user and group specify which Unix user HAProxy operates as.

The last few lines turn on HAProxy’s built in statistics page, which you can view by navigating to the URI in your browser. In this case, that would be http://your_ip/haproxy?stats, but you can view a demo of it here.

Next, we’ll set the default config that will apply to all listen blocks if they don’t make any changes to it:

    log global
    mode http
    option httplog
    option dontlognull
    retries 3
    option redispatch
    timeout connect 5000
    timeout client 10000
    timeout server 10000

We’re setting the default to use the global log setting, operate on HTTP, and set some settings related to connection timeouts.

We’ll create a frontend block that will do the heavy lifting, and forward connections to the backend:

frontend proxy
    bind *:80

    # ACL function declarations
    acl is_abuse src_http_req_rate(Abuse) ge 10 
    acl inc_abuse_cnt src_inc_gpc0(Abuse) gt 0 
    acl abuse_cnt src_get_gpc0(Abuse) gt 0

    # Rules
    tcp-request connection track-sc0 src table Abuse
    tcp-request connection reject if abuse_cnt
    http-request deny if abuse_cnt
    http-request deny if is_abuse inc_abuse_cnt

    option httpclose
    option forwardfor

    use_backend appname

The first line binds this frontend to port 80, where HAProxy will listen on.

The next two sections are for rate limiting. First, the access control list (ACL) functions are declared, which determine if an IP address is abusive. Then, a set of rules will reject a connection if it’s making too many requests.

The forwardfor option will forward the client’s IP address to the server. Since HAProxy acts as a reverse proxy, your nginx server would only see your HAProxy server’s IP address. This option sets the  X-Forwarded-For HTTP header to the client’s IP address.

And finally, we set this frontend block to use the backend “appname,” which we’ll need to create. The backend block simply defines the servers to forward to, along with a few options:

backend appname your_ip:80
    balance roundrobin
    cookie SERVERNAME insert
    server web1 web1_ip:80 check cookie web1
    server web2 web2_ip:80 check cookie web2

The balance directive defines how HAProxy balances requests between servers. The most common option is roundrobin, which will rotate connections through each server in order. If you run into issues with balance, you can try using the option leastconn, which selects based on concurrent connections. If you need users to access the same server over multiple connections, you can use the source option, which selects based on a hash of the client’s IP address.

The last two lines allocate servers to this listen block. You give them a name (web1 and web2) specify their addresses, and then list a few options. Here, we use the check parameter to make sure the server is healthy and accepting connections, and the cookie parameter to set the SERVERNAME cookie (which we inserted directly above) to the name of the server, which is used for session stickiness (so the user doesn’t switch servers while using your site). The balance source option achieves this same effect.

And because we’re using rate limiting, we’ll actually need another backend to store IP addresses:

backend Abuse
    stick-table type ip size 100K expire 30m store gpc0,http_req_rate(10s)

This doesn’t actually forward any connections; it functions as a table to store addresses in. Addresses are flushed after 30 minutes, so addresses deemed abusive will be blocked for 30 minutes.

Finally, you can start the HAProxy service by running:

service haproxy start
Profile Photo for Anthony Heddings Anthony Heddings
Anthony Heddings is the resident cloud engineer for LifeSavvy Media, a technical writer, programmer, and an expert at Amazon's AWS platform. He's written hundreds of articles for How-To Geek and CloudSavvy IT that have been read millions of times.
Read Full Bio »