We’ve got quite a number of different websites on different servers. We use a central haproxy server (well, two, for fail-over) to distribute the various domains to the (django) websites.
There are two special categories I wanted to handle:
Internal-only sites that are only available on our interal IP range. When accessed from elsewhere, you should get a “403” error with an error page saying it is an internal-only site plus a hint to use VPN.
Domains that aren’t found. A 404 with a “we don’t know about this one” error message.
With haproxy 2.2, which is the version we’re using now on ubuntu 22.04,
there’s support for this with http return status 404
or something like
that. Until two months ago, we were on an older ubuntu with haproxy 1.8. There
the trick to accomplish it was to use dummy backends:
backend no-domain-found
# No servers here, it is used for showing the "404" page. Well, haproxy
# knows no 404 itself, so we let the empty backend generate a 503, but we
# sneakily return a 404 error page (including 404 header). See
# https://serverfault.com/q/496460/52614
errorfile 503 /some/where/503-as-404.http
disabled # Don't show it in the interface.
backend deny-external
# External requests to internal resources get denied. No servers here, it
# is used for showing the "403 forbidden" page.
http-request deny
disabled # Don't show it in the interface.
In the list of regular backends, there would be a default_backend
no-domain-found
to shuffle all unknown domains to no-domain-found
. That
had no available backends, so a 503 unavailable
is generated. The
errorfile
directive defines a custom error page including the proper 404
response:
HTTP/1.0 404 Not Found
Cache-Control: no-cache
Connection: close
Content-Type: text/html
{pre}
<h1>404: website not found</h1>
<p>
The website you've requested is not known here.
</p>
{post}
But…. since updating to version 2.2, this trick didn’t work anymore. I’d only get the basic “503 backend unavaible” error. I couldn’t find any documentation as to the cause.
In the end the problem was the ‘disabled’ keyword that I used. With it,
the dummy backend isn’t shown in haproxy’s status page. But somewhere between
1.8 and 2.2, haproxy treated those disabled backends as completely disabled,
not even looking at the errorfile
statement or the http-request deny
line.
After removing the disabled
line, the old dummy backend trick worked
again.
Anyway, perhaps this blog post helps someone :-)
My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):