Watch our on-demand webinar “Introduction to HAProxy” to learn more about the basics of load balancing with HAProxy.
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
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
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.
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:
The structure of this file is as follows:
A section begins when a keyword like
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.
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:
Let’s see how each of these settings works.
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.
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
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 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
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.
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 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.
As your configuration grows, using a
defaults section will help reduce duplication. Its settings apply to all of the
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 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
backend sections after it. Then, place all of your HTTP settings in another
defaults section and follow it with your HTTP
Consider this example:
Let’s discuss what each of these settings mean.
timeout connect / timeout client / timeout server
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
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 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 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
backend sections would use the same mode, it makes sense to specify it in the
defaults section to avoid repetition.
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 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.
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:
Let’s see what these lines mean.
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
crt arguments to instruct HAProxy to manage SSL/TLS terminations, rather than having your web servers doing that.
nbproc, then you can tell each bind directive which process to use with the
processparameter. For example, setting
process 1would bind the listener to the first process.
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 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 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
default_backend directive, HAProxy will return a 503 Service Unavailable error.
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:
Let’s look at some settings you will find in a
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 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
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 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 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
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
Learn more about the essential sections of your usual HAProxy Configuration file in my video:
What About Listen?
As you’ve seen,
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
backend into one. You may prefer the readability gained by having separate
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:
You’ve learned the most important sections of an HAProxy configuration file:
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.
Nice explanation! Just a few comments :
– please really avoid mixing nbproc and nbthread. In 1.8, threads scale less than processes, so if you use threads it’s because you’re facing limitations imposed by processes (such as peers, stick-tables, stats, checks etc) so there’s no reason to use processes. Conversely if you can afford processes, no need to feel the extra overhead of threads that 1.8 has. So in general nbproc+nbthread indicate hesitation.
– haproxy supports loading its configuration from multiple files, and these files are delimited by sections. I personally like to place the global section into a separate file because it’s different. It’s mainly about sizing and resources used by the process, while the other ones describe traffic processing rules. This also simplifies config sharing between multiple machines.
– regarding “maxconn”, it only sets the process-wide limit, but each frontend will still have the default limit (which can be checked with haproxy -vv, often 2000). You should always have one as well in your defaults sections at least as a reminder that the global one is not enough to raise your limits.
– I tend to recommend to have one (or more) “defaults” section for pure TCP settings, place all the TCP instances there, and another (or more) one for pure HTTP settings, followed by the HTTP instances. This avoid accidental mixing of some options.
– it’s a good practice to drop the “listen” keyword for anything HTTP-related. Indeed, while you may find it simpler at first, once you start to add extra components to your application you’ll add new backends, and by then some http-rules will have appeared in your listen section. This will make it very difficult to split it because you won’t know the ones that are specific to the frontend part and the ones specific to the backend part. “listen” mostly stays for compatibility and for pure TCP gateways, which still remain quite common.