Alerts and monitoring

Error pages

You can customize the HTTP error pages clients receive to add your own styling, text, and images. Two scenarios exist:

  • Customize HTTP errors generated by the load balancer itself
  • Customize HTTP errors received from the backend web servers

Customize load balancer errors Jump to heading

This section applies to:

  • HAProxy 2.1 and newer
  • HAProxy Enterprise 2.1r1 and newer
  • HAProxy ALOHA 12.0 and newer

When customizing load balancer errors, you can create multiple groups of error files defined in an http-errors section that can be loaded per proxy / per site. You can also render dynamic content on these pages using template files.

The load balancer supports the following HTTP status code for customization: 200, 400, 401, 403, 404, 405, 407, 408, 410, 413, 425, 429, 500, 501, 502, 503, and 504.

About making changes

The load balancer reads and stores in memory custom error files at the same time it reads the load balancer configuration. If you make changes to the files while the load balancer is running, it will not automatically apply the changes. You must reload the load balancer configurtion to pick up new changes to your custom error files.

Also, you must give the absolute path when defining the location of your custom error files. The load balancer reads these files before it performs a change root or chroot.

Declare groups of HTTP errors Jump to heading

The http-errors section locates custom HTML pages to return to clients when errors occur. By default, the load balancer will serve these pages only if it initiated the error itself. For example, it will return the page for a 503 Service Unavailable error if it can’t reach any backend servers.

To define custom error pages:

  1. Create a file with a .http file extension and add HTTP metadata at the top of the file. The metadata should include the HTTP start line and headers. In the following example, we define a custom 403 error page, and save it as 403.http:

    403.http
    html
    HTTP/1.1 403 Forbidden
    Cache-Control: no-cache
    Connection: close
    Content-Type: text/html
    <!DOCTYPE html>
    <html>
    <body>
    <h1>403 Forbidden</h1>
    <p>Sorry, but you are not authorized to view this page.</p>
    </body>
    </html>
    403.http
    html
    HTTP/1.1 403 Forbidden
    Cache-Control: no-cache
    Connection: close
    Content-Type: text/html
    <!DOCTYPE html>
    <html>
    <body>
    <h1>403 Forbidden</h1>
    <p>Sorry, but you are not authorized to view this page.</p>
    </body>
    </html>

    Note that while this file contains HTML file, it is a .http file instead of an .html file, as it contains both HTML content and HTTP metadata.

  2. In your load balancer configuration, add an http-errors section with one or more errorfile directives, where each specifies an HTTP response status code and the path to an error file. In the following example, we define one custom error page to use for 403 Forbidden errors:

    haproxy
    http-errors myerrors
    errorfile 403 /403.http
    haproxy
    http-errors myerrors
    errorfile 403 /403.http

    You can define different error page files for different response status codes:

    haproxy
    http-errors myerrors
    errorfile 403 /etc/haproxy/errorfiles/403.http
    errorfile 404 /etc/haproxy/errorfiles/404.http
    errorfile 500 /etc/haproxy/errorfiles/500.http
    haproxy
    http-errors myerrors
    errorfile 403 /etc/haproxy/errorfiles/403.http
    errorfile 404 /etc/haproxy/errorfiles/404.http
    errorfile 500 /etc/haproxy/errorfiles/500.http
  3. To use custom error pages, reference the name of the http-errors section by using an errorfiles directive in your frontend:

    haproxy
    frontend www
    bind :80
    default_backend webservers
    errorfiles myerrors
    haproxy
    frontend www
    bind :80
    default_backend webservers
    errorfiles myerrors

Using an older version of the load balancer?

Support for the http-errors directive, useful for declaring multiple groups of HTTP errors which can be used in separate proxy sections, that is, frontends, backends, and so on, was added in version 2.1. Older versions can use the explicit errorfile directive within proxies instead of declaring the HTTP error files within an http-errors section. For versions 2.0 and earlier, place the errorfile directives directly in the frontend definition:

haproxy
frontend www
bind :80
default_backend webservers
errorfile 403 /etc/haproxy/errorfiles/403.http
errorfile 404 /etc/haproxy/errorfiles/404.http
errorfile 500 /etc/haproxy/errorfiles/500.http
haproxy
frontend www
bind :80
default_backend webservers
errorfile 403 /etc/haproxy/errorfiles/403.http
errorfile 404 /etc/haproxy/errorfiles/404.http
errorfile 500 /etc/haproxy/errorfiles/500.http

Use an error template file Jump to heading

This section applies to:

  • HAProxy 2.2 and newer
  • HAProxy Enterprise 2.2r1 and newer
  • HAProxy ALOHA 12.5 and newer

You can use the http-error status directive to set template files for load-balancer-generated errors using its lf-file parameter. Consider the following example:

  1. We create a .http error template file named 504.http to cover the case where the load balancer timed out waiting to receive a response from a server. Because it is a template file, it can render load balancer variables and fetch methods:

    504.html
    html
    HTTP/1.1 504 Gateway Timeout
    Cache-Control: no-cache
    Connection: close
    Content-Type: text/html
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <title>504 Gateway Timeout</title>
    </head>
    <body>
    <main>
    <h1>504 Gateway Timeout</h1>
    The server that timed out is : %[srv_name]
    </main>
    </body>
    </html>
    504.html
    html
    HTTP/1.1 504 Gateway Timeout
    Cache-Control: no-cache
    Connection: close
    Content-Type: text/html
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <title>504 Gateway Timeout</title>
    </head>
    <body>
    <main>
    <h1>504 Gateway Timeout</h1>
    The server that timed out is : %[srv_name]
    </main>
    </body>
    </html>

    We define in the file:

    • HTTP metadata at the top of the file for the 504 Gateway Timeout.
    • The HTML page data to return upon receiving a 504 Gateway Timeout error.
      • The page data includes a reference to the sample fetch srv_name to help identify the potentially troublesoom server.
  2. We reference this template file in our frontend. The syntax for this directive is:

    • http-error status <code> content-type <content-type> lf-file <.http custom error file path>.
    haproxy
    frontend www
    bind :80
    default_backend web_servers
    http-error status 504 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errorfiles/504.http
    backend web_servers
    mode http
    balance roundrobin
    server s1 192.168.1.25:80 check
    server s2 192.168.1.26:80 check
    server s3 192.168.1.27:80 check
    haproxy
    frontend www
    bind :80
    default_backend web_servers
    http-error status 504 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errorfiles/504.http
    backend web_servers
    mode http
    balance roundrobin
    server s1 192.168.1.25:80 check
    server s2 192.168.1.26:80 check
    server s3 192.168.1.27:80 check
    • You must set the content-type of the file; in this case it is text/html; charset=utf-8.
    • Note that we use lf-file instead of file, as we want the load balancer to be able to render the content that contains the sample fetch. When you use file, the content is treated as a raw string and is rendered as such.

The error page returned will name the server that timed out. For example:

text
504 Gateway Timeout
The server that timed out is : s1
text
504 Gateway Timeout
The server that timed out is : s1

http-error status and errorfile

If you specify the errorfile or errorfiles arguments on the http-error status line, you do not need to set the content-type. You also do not need to set content-type if you are returning an empty payload as your error page.

Customize web server errors Jump to heading

You can intercept error responses from backend web servers and replace them with your custom error pages.

  1. In your load balancer configuration, add an http-errors section with one or more errorfile directives, where each specifies an HTTP response status code and the path to an error file. In the following example, we define one custom error page to use for 404 Not Found errors:

    haproxy
    http-errors myerrors
    errorfile 404 /404.http
    haproxy
    http-errors myerrors
    errorfile 404 /404.http
  2. In your frontend, add an errorfiles directive that refers to your http-errors section. Also, add an http-response return directive to intercept any response from the server that has a 404 status. It then, by specifying default-errorfiles, returns the 404 errorfile that was defined in the myerrors section:

    haproxy
    frontend www
    bind :80
    default_backend webservers
    errorfiles myerrors
    http-response return status 404 default-errorfiles if { status 404 }
    haproxy
    frontend www
    bind :80
    default_backend webservers
    errorfiles myerrors
    http-response return status 404 default-errorfiles if { status 404 }
  3. Optional: The default-errorfiles argument instructs the load balancer to use the error files specified by the errorfiles directive within the frontend. Alternatively, you can indicate a different set of error files to use by setting the errorfiles argument on the http-response return line. In the following example, we use the 404 page from the alternative_errors if the status is 404 and the Host header is example.com:

    haproxy
    http-errors myerrors
    errorfile 403 /etc/haproxy/errorfiles/403.http
    errorfile 404 /etc/haproxy/errorfiles/404.http
    errorfile 500 /etc/haproxy/errorfiles/500.http
    http-errors alternative_errors
    errorfile 403 /etc/haproxy/errorfiles/403-alt.http
    errorfile 404 /etc/haproxy/errorfiles/404-alt.http
    errorfile 500 /etc/haproxy/errorfiles/500-alt.http
    frontend www
    bind :80
    default_backend webservers
    http-request set-var(txn.host) req.hdr(host)
    errorfiles myerrors
    http-response return status 404 errorfiles alternative_myerrors if { status 404 } { var(txn.host) example.com }
    http-response return status 404 default-errorfiles if { status 404 } !{ var(txn.host) example.com }
    haproxy
    http-errors myerrors
    errorfile 403 /etc/haproxy/errorfiles/403.http
    errorfile 404 /etc/haproxy/errorfiles/404.http
    errorfile 500 /etc/haproxy/errorfiles/500.http
    http-errors alternative_errors
    errorfile 403 /etc/haproxy/errorfiles/403-alt.http
    errorfile 404 /etc/haproxy/errorfiles/404-alt.http
    errorfile 500 /etc/haproxy/errorfiles/500-alt.http
    frontend www
    bind :80
    default_backend webservers
    http-request set-var(txn.host) req.hdr(host)
    errorfiles myerrors
    http-response return status 404 errorfiles alternative_myerrors if { status 404 } { var(txn.host) example.com }
    http-response return status 404 default-errorfiles if { status 404 } !{ var(txn.host) example.com }

    default-errorfiles in a backend

    The preceding examples use default-errorfiles in a frontend. If you use default-errorfiles in a backend, the error message that the load balancer returns is the error message you have defined in the frontend instead of the error message the backend received from the server.

See also Jump to heading

Do you have any suggestions on how we can improve the content of this page?