How to Install HAProxy on a Raspberry

Cloud case server

HAProxy is available on the Raspbian platform! HAProxy is a high availability, load balancing, and proxying server application. It sits between the Internet and your webservers. HAProxy sends the traffic to each of your servers, round-robin style. Since I’m serving this website on a couple of Raspberries, I thought HAProxy would be a welcome solution to my Raspberry environment.

This, a WordPress website, has a couple of parts. Traffic comes in from the Internet through my fiber modem/firewall. The router port forwards port 80 traffic (web) to my proxy server on port 8000. The proxy server is running HAProxy, which listens on port 8000, and sends the traffic to the proper set of servers, based on the URL that is being requested. Better Done Yourself gets a little more traffic than How to Raspberry so there are 3 Raspberries set up to serve Better Done Yourself. Currently, How to Raspberry only gets two. This describes the “front end”.

The “back-end” is not directly reachable from the Internet. WordPress is a CMS, or “Content Management System”. A CMS relies on a database to store the content of the pages, posts, and comments. The CMS draws the content from the database, formats it into HTML, and hands it off to the web server for perusal by the person browsing the site.

So, now let’s take a look at how HAProxy is configured to be the mediator of web-traffic destined for my web-serving Raspberries. HAProxy also operates on the front-end/back-end principle. From HAProxy’s point of view, the “front-end” is incoming traffic. The “back-end” is the webservers that are going to answer the web requests.

Now, let’s tackle configuring HAProxy. First, we define the frontend and name it www. (By the way, HAProxy is more than capable of serving up more than just web traffic!) For this frontend, we’re going to listen on port 8000 for incoming requests. If it sees a request, it checks a lookup table for the name of the web server to send the page request to:

frontend www
bind *:8000
use_backend %[req.hdr(host),lower,map_dom(/etc/haproxy/domain2backend.map,bk_default)]

Here’s a look at that table. Pretty simple. Just a list on my domains and the backend that serves them. (In this case, we’re talking about the servers that backend HAProxy, not the database that backends WordPress.)

root@proxy:/etc/haproxy# cat domain2backend.map
#domain-name              backend-name
betterdoneyourself.com    betterdy
macdowalls.com            stone
howtoraspberry.com        howto

So, HAProxy has three potential domains for which to route traffic. Each has its own backend. Note that I have chosen a “round-robin” load balancing strategy. This means that HAProxy will attempt to use each server one after the other in order. The first request goes to webs1, the second request to webs2, third request to webs3, fourth request to webs1, fifth request to webs2, and so on.

Also note that I have set up each of the 5 raspberry pi web servers, and added their full IP addresses (including port 80, where all the servers are listening for connections). “stone” is the odd man out. stone is actually an x86_64 LINUX server so it’s not load balanced.

backend stone
mode http
server stone 10.0.0.6:80 check

backend betterdy
mode http
balance roundrobin
server webs1 10.0.0.204:80 check
server webs2 10.0.0.205:80 check
server webs3 10.0.0.206:80 check

backend howto
mode http
balance roundrobin
server wordp1 10.0.0.207:80 check
server wordp2 10.0.0.208:80 check

Finally, the statistics page. I’ve bound THAT to port 80 so I don’t have to browse to a nonstandard port to check on my HAProxy server with my web browser. Here’s the config snippet for that

listen stats
bind :80
mode http
stats enable
stats uri /
stats hide-version

Here’s a shot of my current stats page:

My highly available Raspberry based web server.

Finally, here’s the entirety of my running config, for your convenience:

global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global

mode http
option tcplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

frontend www
bind *:8000
use_backend %[req.hdr(host),lower,map_dom(/etc/haproxy/domain2backend.map,bk_default)]

backend stone
mode http
server stone 10.0.0.6:80 check
backend betterdy
mode http
balance roundrobin
server webs1 10.0.0.204:80 check
server webs2 10.0.0.205:80 check
server webs3 10.0.0.206:80 check

backend howto
mode http
balance roundrobin
server wordp1 10.0.0.207:80 check
server wordp2 10.0.0.208:80 check

listen stats
bind :80
mode http
stats enable
stats uri /
stats hide-version

I haven’t gone over every bit of the config. I’ll leave that as homework. I will however give you some troubleshooting tips:

Check your configuration with:

haproxy -c -f /etc/haproxy/haproxy.cfg

Then try to start it manually with:

haproxy -db -f /etc/haproxy/haproxy.cfg

Here’s the parts list: http://howtoraspberry.com/index.php/2020/04/24/parts-to-build-the-raspberry-webserver/

Author: John

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.