Maintenance Pages With HAProxy
2021-07-26
Edit: 31/7/2021: Add content for maintenance pages.
I currently work with a group of very smart individuals and I learn a lot from them on almost daily basis. One thing they have done which I found cool was using Terraform to configure the AWS Application Load Balancer to display the notice during maintenance windows.
I wanted to see if my favorite load balancer HAProxy could do it and turns out it can, and you can find the required configuration below. It assumes running multiple web applications with one server each, modifying the configuration to suit your requirements should be simple to do.
/etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-dh-param-file /etc/haproxy/dhparams.pem
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 500
timeout client 5000
timeout server 5000
frontend terminator
bind PUBLIC_IP:80
bind PUBLIC_IP:443 ssl crt-list /etc/haproxy/certs alpn h2,http/1.1
# LetsEncrypt
acl acme path_dir /.well-known/acme-challenge
acl maintenance_mode hdr(host),map(/etc/haproxy/maintenance) -m found
acl whitelist src -f /etc/haproxy/whitelist
http-response set-header Strict-Transport-Security max-age=15768000 if { ssl_fc }
http-request set-header X-Forwarded-Proto https if { ssl_fc }
# The ACME protocol doesn't like it when it gets redirected
redirect scheme https code 301 if !{ ssl_fc } !acme
use_backend acme if acme
# Actual Routing
use_backend %[req.hdr(host),lower,map(/etc/haproxy/maintenance)] if maintenance_mode !whitelist
use_backend %[req.hdr(host),lower,map(/etc/haproxy/backends)]
backend acme
server acmetool 127.0.0.1:402
# Actual backends
backend webapp1
server server1 127.0.0.1:8080
backend webapp2
server server1 127.0.0.1:8081
# Maintenance backends
backend webapp1_maintenance
errorfile 503 /etc/haproxy/maintenance_pages/webapp1.http
backend webapp2_maintenance
errorfile 503 /etc/haproxy/maintenance_pages/webapp2.http
/etc/haproxy/whitelist
# Networks listed here bypass all maintenance pages
192.168.0.0/24
/etc/haproxy/maintenance
# Uncomment lines below to enable the maintenance page for the desired web application
#webapp1.com webapp1_maintenance
#webapp2.com webapp2_maintenance
/etc/haproxy/backends
webapp1.com webapp1
webapp2.com webapp2
As for the maintenance pages
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<html><body><h1>Maintenance</h1>
The system is undergoing maintenance, sorry for the inconvenience
</body></html>
About Me
Dev gone Ops gone DevOps. Any views expressed on this blog are mine alone and do not necessarily reflect the views of my employer.