An HAProxy configuration file guides the behavior of your HAProxy load balancer. In this post, we demonstrate its four most essential sections.

There are four essential sections to an HAProxy configuration file. They are global, defaults, frontend, and backend. These four sections define how the server as a whole performs, what your default settings are, and how client requests are received and routed to your backend servers.

If you compare the world of reverse proxies to an Olympic relay race, then global, defaults, frontend and backend are the star runners. Each section plays a vital role, handing the baton to the next in line. Like an Olympic relay team, an HAProxy load balancer’s power and performance is achieved by combining the unique talents of each section. Let’s meet them and see how they team up.

The Format

If you’re using HAProxy Enterprise to get ahold of its advanced features, the configuration file can be found at /etc/hapee-1.8/hapee-lb.cfg. If you’re using the Community Edition, it’s at /etc/haproxy/haproxy.cfg. You can test your configuration changes by calling the haproxy executable with the -c parameter, such as:

haproxy -c -f /etc/hapee-1.8/hapee-lb.cfg

The structure of this file is as follows:

global
    # global settings here

defaults
    # defaults here

frontend
    # a frontend that accepts requests from clients

backend
    # servers that fulfill the requests

A section begins when a keyword like global or defaults is encountered and is comprised of all of the lines that follow until you reach another section keyword. Blank lines and indentation are ignored. So, the global section continues until you get to, say, a defaults keyword on its own line.

Let’s imagine that you have a single website that you want to make available to clients, such as www.mysite.com. Within your private network, you’ll have two web servers that host the files for this site. Of course, you could have many more servers than this, but for demonstration purposes, we’ll leave it at two. So that both servers can be utilized, they are load balanced to handle the requests, meaning that they take turns receiving and responding to requests. HAProxy is a reverse proxy that sits in front of the two web servers and routes requests to them.

As we go along, you can learn more about the configuration settings by reading the official documentation. Let’s see some important directives for each section.

Global

At the top of your HAProxy configuration file is the global section, identified by the word global on its own line. Settings under global define process-wide security and performance tunings that affect HAProxy at a low level.

Consider the following example:

global
    maxconn 50000
    log /dev/log local0
    user haproxy
    group haproxy
    stats socket /run/haproxy/admin.sock user haproxy group haproxy mode 660 level admin
    nbproc 2
    nbthread 4
    cpu-map auto:1/1-4 0-3
    ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

Let’s see how each of these settings works.

maxconn

The maxconn setting limits the maximum number of connections that HAProxy will accept. Its purpose is to protect your load balancer from running out of memory. You can determine the best value for your environment by consulting the sizing guide for memory requirements.

Did You Know? In addition to the memory consumed by processing connections, additional memory is used by stick tables, map files, and ACL files that you’ve defined.

log

The log setting ensures that warnings emitted during startup and issues that arise during runtime get logged to syslog. It also logs requests as they come through. You can target the traditional UNIX socket where Syslog or journald, listen, /dev/log, or specify a remote rsyslog server so that log data is preserved externally to your load balancing server. Set a Syslog facility, which is typically local0, which is a facility categorized for custom use. Note that in order to read the logs, you will need to configure any of the syslog daemons, or journald, to write them to a file.

user / group

The user and group lines tell HAProxy to drop privileges after initialization. Linux requires processes to be root in order to listen on ports below 1024. You’ll also typically want your TLS private keys to be readable only by root as well. Without defining a user and group to continue the process as, HAProxy will keep root privileges, which is a bad practice. Be aware that HAProxy itself does not create the user and group and so they should be created beforehand.

stats socket

The stats socket line enables the Runtime API, which you can use to dynamically disable servers and health checks, change the load balancing weights of servers, and pull other useful levers. You can learn more by reading our blog post Dynamic Configuration with the HAProxy Runtime API.

nbproc / nbthread

The nbproc and nbthread settings specify the number of processes and threads, respectively, that HAProxy should spawn on startup. This can increase the efficiency of your load balancer. However, each process created by nbproc has its own stats, stick tables, health checks, and so on. Threads created with nbthread, on the other hand, share them. You may use one or the other or both settings. HAProxy performs quite well with only one process and thread, unless you are doing a lot of TLS terminations, which benefits from using multiple CPU cores. Read our blog post Multithreading in HAProxy to learn more.

Did You Know? When setting either of these you will also want to set cpu-map to ensure that the processes are pinned to a specific core for maximum performance.

ssl-default-bind-ciphers

The ssl-default-bind-ciphers setting enumerates the SSL and TLS ciphers that every bind directive will use by default. It can be overridden with a more specific setting by adding the bind directive’s ciphers parameter. It takes a list of cipher suites in order of preference. HAProxy will select the first one listed that the client also supports, unless the prefer-client-ciphers option is enabled. Try using the Qualys SSL Server Test to see how strong your chosen ciphers are and which browsers you’ll be able to support.

ssl-default-bind-options

The ssl-default-bind-options setting configures SSL/TLS options such as ssl-min-ver to disable support for older protocols. For example, you might choose to accept only connections that use a TLS version of 1.2 or newer.

Defaults

As your configuration grows, using a defaults section will help reduce duplication. Its settings apply to all of the frontend and backend sections that come after it. You’re still free to override those settings within the sections that follow.

You also aren’t limited to having just one defaults. Subsequent defaults sections will override those that came before and reset all options to their default values.

So, you might decide to configure a defaults section that contains all of your TCP settings and then place your TCP-only frontend and backend sections after it. Then, place all of your HTTP settings in another defaults section and follow it with your HTTP frontend and backend sections.

Consider this example:

defaults
    timeout connect 10s
    timeout client 30s
    timeout server 30s
    log global
    mode http
    option httplog
    maxconn 3000

Let’s discuss what each of these settings mean.

timeout connect / timeout client / timeout server

The timeout connect setting configures the time that HAProxy will wait for a TCP connection to a backend server to be established. The “s” suffix denotes seconds. Without any suffix, the time is assumed to be in milliseconds. The timeout client setting measures inactivity during periods that we would expect the client to be speaking, or in other words sending TCP segments. The timeout server setting measures inactivity when we’d expect the backend server to be speaking. When a timeout expires, the connection is closed. Having sensible timeouts reduces the risk of deadlocked processes tying up a connections that could otherwise be reused.

When operating HAProxy in TCP mode, which is set with mode tcp, timeout server should be the same as timeout client. That’s because HAProxy doesn’t know which side is supposed to be speaking and, since both apply all the time, having different values makes confusion more likely.

log global

The log global setting is a way of telling each subsequent frontend to use the log setting that you defined in the global section. This isn’t required for logging, as new log lines can be added here or in each frontend. However, in most cases wherein only one syslog server is used, this is common.

mode

The mode setting defines whether HAProxy operates as a simple TCP proxy or if it’s able to inspect incoming traffic’s higher-level HTTP messages. The alternative to specifying mode http is to use mode tcp, which operates at the faster, but less-aware, level. If most of your frontend and backend sections would use the same mode, it makes sense to specify it in the defaults section to avoid repetition.

maxconn

The maxconn setting limits the number of connection that each frontend will accept and, by default, is set to 2000. If you want to allow more connections, you can increase it here up to your global maxconn. On the other hand, you may wish to use a number that gives each frontend a fair share of the global connections.

option httplog

The option httplog setting, or more rarely option tcplog, tells HAProxy to use a more verbose log format when sending messages to Syslog. You will generally prefer option httplog over option tcplog in your defaults section because when HAProxy encounters a frontend that uses mode tcp, it will emit a warning and downgrade it to option tcplog anyway.

If neither is specified, then the connect log format is used, which has very few details other than the client and backend IP addresses and ports. Another option is to define a custom log format with the log-format setting, in which case option httplog and option tcplog aren’t necessary.

Frontend

When you place HAProxy as a reverse proxy in front of your backend servers, a frontend section defines the IP addresses and ports that clients can connect to. You may add as many frontend sections as needed for exposing various websites to the Internet. Each frontend keyword is followed by a label, such as www.mysite.com, to differentiate it from others.

Consider the following example:

frontend www.mysite.com
    bind 10.0.0.3:80
    bind 10.0.0.3:443 ssl crt /etc/ssl/certs/mysite.pem
    http-request redirect scheme https unless { ssl_fc }
    use_backend api_servers if { path_beg /api/ }
    default_backend web_servers

Let’s see what these lines mean.

bind

A bind setting assigns a listener to a given IP address and port. The IP can be omitted to bind to all IP addresses on the server and a port can be a single port, a range, or a comma-delimited list. You’ll often use the ssl and crt arguments to instruct HAProxy to manage SSL/TLS terminations, rather than having your web servers doing that.

Did You Know? If you have enabled HAProxy to use multiple processes via nbproc, then you can tell each bind directive which process to use with the process parameter. For example, setting process 1 would bind the listener to the first process.

http-request redirect

A http-request redirect setting responds to the client that they should try a different URL. In our example, clients that request your website over non-encrypted HTTP are redirected to the HTTPS version of the site.

use_backend

The use_backend setting chooses a backend pool of servers to respond to incoming requests if a given condition is true. It is followed by an ACL statement, such as if path_beg /api/, that allows HAProxy to select a specific backend based on some criteria, such as checking if the path begins with /api/. To learn more about ACLs, read our blog post Introduction to HAProxy ACLs. These lines aren’t required and many frontend sections only have a default_backend line and no special selection rules.

default_backend

The default_backend setting is found in nearly every frontend and gives the name of a backend to send traffic to if a use_backend rule doesn’t send it elsewhere first. If a request isn’t routed by a use_backend or default_backend directive, HAProxy will return a 503 Service Unavailable error.

Backend

A backend section defines a group of servers that will be load balanced and assigned to handle requests. You’ll add a label of your choice to each backend, such as web_servers. It’s generally, pretty straightforward and you won’t often need many settings here.

Consider this example:

backend web_servers
    balance roundrobin
    cookie SERVERUSED insert indirect nocache
    option httpchk HEAD /
    default-server check maxconn 20
    server server1 10.0.1.3:80 cookie server1
    server server2 10.0.1.4:80 cookie server2

Let’s look at some settings you will find in a backend section.

balance

The balance setting controls how HAProxy will select the server to respond to the request if no persistence method overrides that selection. A persistence method might be to always send a particular client to the same server based on a cookie. Common load balancing values include roundrobin, which just picks the next server and starts over at the top of the list again, and leastconn, where HAProxy selects the server with the fewest active sessions.

cookie

The cookie setting enables cookie-based persistence. It tells HAProxy to send a cookie named SERVERUSED to the client, and to associate it with the name of the server that gave the initial response. This causes the client to continue speaking with that server for the duration of their session. Note that the name of the server is set with a cookie argument on the server line.

option httpchk

The option httpchk setting causes HAProxy to send Layer 7 (HTTP) health checks instead of Layer 4 (TCP) checks to your backend servers. Servers that don’t respond are not served any more requests. Whereas TCP checks succeed if they’re able to make a connection to the backend server’s IP and port, HTTP health checks expect to get back a successful HTTP response. Smarter health checks are instrumental in removing unresponsive servers, even if unresponsive means just getting a bad HTTP response like 500 Server Error.

By default, an HTTP health check makes a request to the root path, /, using the OPTIONS verb. However, arguments specified here can customize that. HAProxy will treat any check that gets a 2xx or 3xx response code to be successful, although this too can be customized with an http-check line. Using option httpchk isn’t restricted to backends that use mode http, so servers that communicate using HTTP can be checked regardless of the proxying mode.

default-server

The default-server setting configures defaults for any server lines that follow, such as enabling health checks, max connections, etc. This can make your configuration easier to read and modify. Alternatively, you can specify these arguments on each server.

server

The server setting is the heart of the backend. Its first argument is a name, followed by the IP address and port of the backend server. You can specify a domain name instead of an IP address. In that case, it will be resolved at startup or, if you add a resolvers argument, it will be updated during runtime. If the DNS entry contains an SRV record, the port and weight will be filled in from it too. If the port isn’t specified, then HAProxy will use the same port that the client connected on, which is useful for randomly used ports such as for active-mode FTP.

Although we added option httpchk to set up HTTP-based health checking of our servers, each server must opt in to health checks by adding a check argument. This can be set on the server line or, as we’ve done in this example, the default-server line.

Every server line should have a maxconn setting that limits the maximum number of concurrent requests that the server will be given. Even if it’s just a guess, having a value here puts you on the right foot for avoiding saturating your servers with requests and gives a baseline that can be adjusted later. In this example, we’ve set this on the default-server line.

Did You Know? We introduced a new setting called server-template that can be used to create placeholder servers that a service discovery tool could then fill in with the right addresses and ports. Read about it in our blog post What’s New in HAProxy 1.8.

What About Listen?

As you’ve seen, frontend and backend sections receive traffic and send it to a pool of servers. You can also use listen sections to do the same thing. They, essentially, combine the functionality of a frontend and backend into one. You may prefer the readability gained by having separate frontend and backend sections, especially when using HTTP mode with its many options, or you may favor a more concise configuration, making listen the preferred approach. In either case, you have the full power of HAProxy at your fingertips!

Here’s a simple example of a listen used to serve up the HAProxy Stats page:

listen stats
    bind *:8404
    stats enable
    stats uri /monitor
    stats refresh 5s

Conclusion

You’ve learned the most important sections of an HAProxy configuration file: global, defaults, frontend and backend. This will get you pretty far. After you’ve become a pro at implementing the basics, you might try setting up DNS resolution with a resolvers section or configuring email notifications with a mailers section. Or, you might try setting up two instances of HAProxy and exploring how a peers section keeps them in sync.

Did you find this post helpful? What else would you like to see? Leave us a comment here or follow us on Twitter. Want to explore the advanced features available in HAProxy Enterprise? Sign up for a free trial or contact us to learn more.

SHARE THIS ARTICLE