HAProxy, which stands for High Availability Proxy, is a popular open source software TCP/HTTP Load Balancer and proxying solution which can be run on Linux, Solaris, and FreeBSD. Its most common use is to improve the performance and reliability of a server environment by distributing the workload across multiple servers (e.g. web, application, database). It is used in many high-profile environments, including: GitHub, Imgur, Instagram, and Twitter.
In this tutorial, we will go over how to use HAProxy for SSL termination, for traffic encryption, and for load balancing your web servers. We will also show you how to use HAProxy to redirect HTTP traffic to HTTPS.
Native SSL support was implemented in HAProxy 1.5.x, which was released as a stable version in June 2014.
To complete this tutorial, you must have or obtain the following:
If you do not already have an SSL certificate and private key pair, please obtain one before continuing. Here are a few tutorials that contain steps that cover creating SSL certificates:
To implement SSL termination with HAProxy, we must ensure that your SSL certificate and key pair is in the proper format, PEM. In most cases, you can simply combine your SSL certificate (.crt or .cer file provided by a certificate authority) and its respective private key (.key file, generated by you). Assuming your certificate file is called example.com.crt
, and your private key file is called example.com.key
, here is an example of how to combine the files:
cat example.com.crt example.com.key > example.com.pem
sudo cp example.com.pem /etc/ssl/private/
This creates the combined PEM file, called example.com.pem
and copies it to /etc/ssl/private
. As always, be sure to secure any copies of your private key file, including the PEM file (which contains the private key).
In some cases, you may need to copy your CA root certificate and CA intermediate certificates into your PEM file.
Here is the environment that we are starting with:
If your environment differs from the example, like if you are already using SSL on the web server or you have a separate database server, you should be able to adapt this tutorial to work with your environment.
If you are unfamiliar with basic load-balancing concepts or terminology, like layer 7 load balancing or backends or ACLs, here is an article that explains the basics: An Introduction to HAProxy and Load Balancing Concepts.
By the end of this tutorial, we want to have an environment that looks like this:
That is, your users will access your website by connecting to your HAProxy server via HTTPS, which will decrypt the SSL session and forward the unencrypted requests to your web servers (i.e. the servers in www-backend) via their private network interfaces on port 80. Your web servers will then send their responses to your HAProxy server, which will encrypt the responses and send them back to the user that made the original request.
You can set up your www-backend with as many web servers as you want, as long as they serve identical content. In other words, you can set this up with a single server then scale it out later by adding as many servers as you want. Remember, as your traffic increases, your HAProxy server may become a performance bottleneck if it does not have enough system resources to handle your user traffic.
Note: This tutorial does not cover how to ensure that your web/application servers serve the same content because that is often application or web server dependent.
Create a new VPS with private networking. For this tutorial, we will call it haproxy-www, but you may call it whatever you want.
In our haproxy-www VPS, add the dedicated PPA to apt-get:
sudo add-apt-repository ppa:vbernat/haproxy-1.6
Then update your apt cache:
sudo apt-get update
Then install HAProxy 1.6 with apt-get with the following command:
sudo apt-get install haproxy
Now that HAProxy 1.6 is installed, let’s configure it!
HAProxy’s configuration file is located at /etc/haproxy/haproxy.cfg
and is divided into two major sections:
Again, if you are unfamiliar with HAProxy or basic load-balancing concepts and terminology, please refer to this link: An Introduction to HAProxy and Load Balancing Concepts.
All of the HAProxy configuration should be done on your HAProxy VPS, haproxy-www.
Open haproxy.cfg in an editor:
sudo vi /etc/haproxy/haproxy.cfg
You will see that there are two sections already defined: global and defaults.
The first thing you will want to do is set maxconn to a reasonable number. This setting affects how many concurrent connections HAProxy will allow, which can affect QoS and prevent your web servers from crashing from trying to serve too many requests. You will need to play around with it to find what works for your environment. Add the following line (with a value you think is reasonable) to the global section of the configuration
maxconn 2048
Add this line, to configure the maximum size of temporary DHE keys that are generated:
tune.ssl.default-dh-param 2048
Next, in the defaults section, add the following lines under the line that says mode http
:
option forwardfor
option http-server-close
The forwardfor option sets HAProxy to add X-Forwarded-For headers to each request, and the http-server-close option reduces latency between HAProxy and your users by closing connections but maintaining keep-alives.
Using HAProxy stats can be useful in determining how HAProxy is handling incoming traffic. If you would like to enable the HAProxy stats page, add the following lines in the defaults section (substitute user and password with secure values):
stats enable
stats uri /stats
stats realm Haproxy\ Statistics
stats auth user:password
This will allow you to look at the HAProxy stats page by going to your domain on /stats
(e.g. https://example.com/stats).
Do not close the config file yet! We will add the proxy configuration next.
The first thing we want to add is a frontend to handle incoming HTTP connections. At the end of the file, let’s add a frontend called www-http. Be sure to replace haproxy_www_public_IP
with the public IP of your haproxy-www VPS:
frontend www-http
bind haproxy_www_public_IP:80
reqadd X-Forwarded-Proto:\ http
default_backend www-backend
Here is an explanation of what each line in the frontend config snippet above means:
haproxy_www_public_IP
with haproxy-www’s public IP address. This tells HAProxy that this frontend will handle the incoming network traffic on this IP address and port 80 (HTTP)Next, we will add a frontend to handle incoming HTTPS connections. At the end of the file, let’s add a frontend called www-https. Be sure to replace haproxy_www_public_IP
with the public IP of your haproxy-www VPS:
frontend www-https
bind haproxy_www_public_IP:443 ssl crt /etc/ssl/private/example.com.pem
reqadd X-Forwarded-Proto:\ https
default_backend www-backend
haproxy_www_public_IP
with haproxy-www’s public IP address, and example.com.pem
with your SSL certificate and key pair in combined pem format. This tells HAProxy that this frontend will handle the incoming network traffic on this IP address and port 443 (HTTPS).After you are finished configuring the frontends, continue adding your backend by adding the following lines. Be sure to replace the highlighted words with the respective private IP addresses of your web servers:
backend www-backend
redirect scheme https if !{ ssl_fc }
server www-1 www_1_private_IP:80 check
server www-2 www_2_private_IP:80 check
Here is an explanation of what each line in the backend config snippet above means:
Now save and exit haproxy.cfg
. HAProxy is now ready to be started, but let’s enable logging first.
Enabling logging in HAProxy is very simple. First edit the rsyslog.conf file:
sudo vi /etc/rsyslog.conf
Then find the following two lines, and uncomment them to enable UDP syslog reception. It should look like the following when you are done:
$ModLoad imudp
$UDPServerRun 514
$UDPServerAddress 127.0.0.1
Now restart rsyslog to enable the new configuration:
sudo service rsyslog restart
HAProxy logging is is now enabled! The log file will be created at /var/log/haproxy.log
once HAProxy is started.
On haproxy-www, start HAProxy to put your configuration changes into effect:
sudo service haproxy restart
HAProxy is now performing SSL termination and load balancing your web servers! Your load balanced server is now accessible to your user via the public IP address or domain name of your load balancer, haproxy-www! There are a few things that you will want to check, to make sure everything is set up correctly.
Note: If you’re using an application that needs to know its own URL, like WordPress, you need to change your URL setting from “http” to https". To follow the WordPress example, you would go to your WordPress General Settings, then change the WordPress Address (URL) and the Site Address (URL) from “http” to “https”.
Now you have a load balancer solution that handles your SSL connections and can be used to horizontally scale out your server environment. Feel free to combine what you have learned in this guide with other HAProxy guides to improve your environment even further!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Adding a load balancer to your server environment is a great way to increase reliability and performance. The first tutorial in this series will introduce you to load balancing concepts and terminology, followed by two tutorials that will teach you how to use HAProxy to implement layer 4 or layer 7 load balancing in your own WordPress environment. The last tutorial covers SSL termination with HAProxy.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Great article! I had one issue that I’m mentioning here in case anyone else runs into the same issue. All worked well when I tested the setup with a class 1 cert. However when I upgraded to a class 2 wildcard cert, Android’s browser and Chrome for Android both showed my site as insecure (all the warnings and the option to report it to Google). My solution was to remove the root cert (ca.pem for StartSSL) from my combined pem file.
How do we determine how large of a droplet we need as a load balancer? Is there a need for load balancer redundancy?
i use ubuntu 16.04 newest on DO. not found $ModLoad imudp $UDPServerRun 514 $UDPServerAddress 127.0.0.1 on rsyslog.conf . so how?
After adding the bind statement in the frontend for SSL in the haproxy.cfg. I am getting the below error
(bind xx.xx.xx.xx:443 ssl crt /etc/haproxy/ssl/dummywebsite.pem)
‘bind’ only supports the ‘transparent’, ‘defer-accept’, ‘name’, ‘id’, ‘mss’ and ‘interface’ options.Excellent tutorial. We are struggling with an issue and cannot find direction. We need for the client (a program, technically, not a browser, doing HTTPS/POST) to connect SSL x.y or TLS 1.0 to HAPROXY, terminate there, and have HAPROXY connect that to the third party server with ONLY TLS 1.2 and SHA256. The client program can point to any address which would be the local HAPROXY on Linux, and then it has to go out to the URL of the 3rd party with strong connection.
We are willing to PAY handsomely for assistance to make this work. We do not have proxy expertise in house and are under a time constraint.
Anyone who can assist, please reply here, or if you can contract, email me slashsplat at gmail dot com.
This comment has been deleted
Hey thanks for the great tutorial.
Is there a way to prevent accessing the haproxy droplet directly over its IP address? I have updated dns config to point a domain to the haproxy, but I don’t want the haproxy be accessible directly over its IP address.
How To Pass arguments to LUA from HAProxy config. I am trying to pass certificate DN information for client and CA, but getting error in haproxy config check.
HAProxy LUA config
global lua-load /usr/sbin/lua-choose-backend.lua
frontend http-in mode http
/usr/sbin/lua-choose-backend.lua
function choose_backend(txn, arg1, arg2) core.log(core.info, “Hello World”) core.log(core.info, arg1) core.log(core.info, arg2)
end
core.register_fetches(“choose_backend”, choose_backend)
$ haproxy -c -f /etc/haproxy/haproxy.cfg
[WARNING] 133/050028 (6381) : parsing [/etc/haproxy/haproxy.cfg:88] : ‘acl’ : sample fetch <lua.choose_backend([ssl_c_s_dn> failed with : missing closing ‘)’ after arguments to fetch keyword ‘lua.choose_backend’ [ALERT] 133/050028 (6381) : Proxy ‘http-in’: unable to find required use_backend: ‘%[lua.choose_backend([ssl_c_s_dn],’.
R
Firstly, thank you very much for these tutorials. They’ve been a great help.
Has anyone been able to get this working with Wordpress using apache?
I’m able to get the SSL to work smoothly with my non-wordpress application but once I navigate to the wordpress site I’m getting a lot of assets being served over http and https and getting errors. I’ve tried updating the wordpress address and site address in the wordpress general->settings but that hasn’t seem to fix the issue. Any help would be greatly appreciated.
Hello Mitchell,
Hope you are doing great.I have one query. I have successfuuly intsalled HAproxy Load Balancer and getting output but I have to proper tuning of HAproxy. I have one 8 GB droplet and two 4 GB droplet. On 8 Gb droplet installed HAproxy and other two droplet Nginx Webserver.I am using Neo4j technology and Laravel. Right now I am getting 300 concurrent users in 10 sec after 502 Bad Gateway Error.What should i do for atleast 5000 concurrent users in 10 sec. Is it possible using Horizontal Scaling or need to only vertical scaling.