Rules, conditions and error pages¶
The publish wizard covers the common case: a name, a pool, a certificate. The objects on this page are for what it does not — a redirect that only applies from outside the LAN, a header set on one path, a list of visitors' networks kept in one place, a 503 page in your own words. All of them live under Advanced › HAProxy except address lists, which sit under Access because they are about who gets in. Everything here is part of the shared configuration and reaches every node like the rest.
- Rules: any of these, and all of those
- The rule wizard
- The condition wizard
- Address lists
- Error pages
Rules: any of these, and all of those¶
A rule on Advanced › HAProxy › Rules tests two lists of conditions. Any
of these — one of them must match. All of these — every one must,
together with one of the first. HAProxy has no parentheses, so a rule for
"tv.example.com or films.example.com, from the LAN" is written out as the
alternatives it is: use_backend be_tv if acl_host-tv acl_lan ||
acl_host-films acl_lan. Leave both lists empty and the rule applies
unconditionally.
The Rules table says what a rule does and when, in words rather than HAProxy's
names: route to a pool, redirect to HTTPS, deny, and its test as
(a or b) and c. The Conditions table does the same — host is, path starts
with, from network.
The shape a rule is stored in. A rule saved before 2.0 held one list and an operator, and a node still on 1.x reads only that shape. So a rule with alternatives only — things under any of these and nothing under all of these — is stored in the old one-list shape, which every version renders the same; the two-list shape is used only when both lists are filled. A 1.x node given such a rule would apply it without its conditions, which is why the Cluster page warns when reachable nodes run 1.x: upgrade them before editing rules or services. The editor opens an old rule whose operator was or with its conditions under Any of these.
The publish wizard writes the two-list shape only when a service needs it: several names and something that must hold for each of them. A condition added to a service's rule by hand on the Rules page — a source list, a header test — is kept when the service is edited, and holds for every name the service answers to. Before 2.0 an edit replaced the whole list, and such a condition was gone.
A single condition can also hold several values separated by spaces —
tv.example.com films.example.com, or two networks — and matches any of them.
A condition a rule still tests cannot be deleted: the request is refused (409) and the message names the rules. Take it off them first.
The rule wizard¶
New rule on the Rules page builds a rule in one dialog, read as a sentence, and Edit on a row opens the same dialog for that rule: the wizard is the editor, and asks for everything a rule holds.
On: the Public Services the rule applies to — the wizard attaches the rule there and places it by how specific it is, where the plain editor leaves that to the listener's own form. When: the conditions, typed in place — host is, path starts with, from network, from address list, HTTP header, raw ACL and the rest — sorted into any of these and all of these; an existing condition can be picked instead, and a typed one that already exists is reused rather than made twice. Then: the action, with only its own fields shown.
Preview asks HAProxy: the result is rendered and checked with haproxy -c
against staged copies of the files it names, and the dialog shows the verdict
and the listener's generated lines. A rule HAProxy would not load is refused
on Save with HAProxy's own words, before anything is stored. A rule from before
2.0 opens with its conditions under any of these. Conditions the wizard made
for a rule go when the rule stops testing them and nothing else does; a
condition made by hand stays.
Rules a service holds for itself — deny, headers, redirects, raw lines, acted on inside the service's pool — are picked in the publish wizard's Advanced section rather than built here; see Configuration.
The condition wizard¶
Advanced · HAProxy › Conditions, under Rules, lists them. Most are made on the way, by the rule wizard; this page is for the rest. New condition asks one test in words: what to look at — host is, path starts with, from network, from address list, HTTP header, URL parameter, SNI, raw ACL — what it should be, and whether to turn it around. Edit on a row opens the same dialog.
Try it takes a sample request (a host, a path, a source address, a header
value) and says whether the condition would match it, shows the acl line it
renders to, and HAProxy's verdict from haproxy -c; a raw ACL is left to
HAProxy alone, and one it would refuse is refused on Save. A typed test
identical to an existing condition is reused rather than made twice, and
Edit on a row opens it the same way.
Address lists¶
Access › Address Lists. A named set of networks, one address or CIDR per line. A list is named from a pool's Allowed networks (in the wizard and on the Backend Pools page), from the networks that skip the sign-in, from a condition of type from address list, and from CrowdSec's Never ask about. Change the list and every service that names it follows at the next Apply. The point is the visitor whose home address changes every few weeks: edited in one place, not on every service that lets them in.
Wherever a list is picked, the checklist shows each list's description beside its name, and an empty checklist offers a Create one link to this page.
Typed networks and named lists count together. A list of more than forty networks is declared as a named ACL over several lines, since HAProxy reads at most 64 words from one. A list deleted while a pool still names it contributes nothing, which can only narrow who gets in; a pool left with no readable network at all refuses everyone.
Error pages¶
Advanced › HAProxy › Error Pages. What visitors see when HAProxy itself
answers with an error: no server left (503), a refused address (403), a rate
limit (429), a paused service (503). A page serves one or more status codes;
{error_code} and {error_message} in its HTML are filled in per code, so one
page can stand for several. Load from file reads a local .html into the
editor; nothing is uploaded, and the page is saved with the configuration like
any other object.
A page is part of the shared configuration, so it reaches every node the way
everything else does. Each node writes its pages to /etc/haproxy/error-pages/
(HAM_ERROR_DIR, one <name>-<code>.http and .html per code) at Apply, and
the generated haproxy.cfg names them with errorfile: in defaults for a
page that is used for every service, inside a pool's own block for the pages
that pool picks (the wizard's Advanced section, and Error pages on the
Backend Pools page), which win for that pool. A paused service answers with its
503 page too. Validation — the form's Save, a wizard's Preview — renders
against a staged copy of the pages in a temporary directory, so nothing under
/etc/haproxy changes until Apply.
Two limits come from HAProxy. It can only replace the responses it generates itself — 400, 401, 403, 404, 405, 407, 408, 410, 413, 425, 429, 431, 500, 501, 502, 503 and 504; a 404 from a server behind the proxy passes through as the server sent it, and a page for any other code is refused. And the whole response has to fit HAProxy's buffer, 16 kB unless tuned, so a page over 14 kB of HTML is refused at the form: link an image rather than embedding it, or inline a small SVG.
A page is HTML you wrote, served as it is to anonymous visitors — the same trust the app already places in a raw ACL or an Extra directives line. Only an administrator can author one.