Shami's Blog

Sysadmin, Because Even Developers Need Heroes

Maintenance Pages With HAProxy

2021-07-26 by Mohammad H. Al-Shami

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

    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    user haproxy
    group haproxy

    # See:
    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

    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

# Actual backends
backend webapp1
    server server1

backend webapp2
    server server1

# Maintenance backends
backend webapp1_maintenance
    errorfile 503 /etc/haproxy/maintenance_pages/webapp1.http

backend webapp2_maintenance
    errorfile 503 /etc/haproxy/maintenance_pages/webapp2.http


# Networks listed here bypass all maintenance pages


# Uncomment lines below to enable the maintenance page for the desired web application  webapp1_maintenance  webapp2_maintenance

/etc/haproxy/backends  webapp1  webapp2

As for the maintenance pages

HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html

The system is undergoing maintenance, sorry for the inconvenience

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.