Implementing Custom 503 Error Pages in Varnish: Replacing Guru Meditation with HTML


8 views

When Varnish encounters backend issues, it shows the infamous "Guru Meditation" error page by default. While amusing, this doesn't provide useful information to visitors or maintain brand consistency. Here's how to replace it with a professional custom HTML page.

Add this to your VCL file (typically default.vcl) to handle 503 errors:


sub vcl_backend_error {
    set beresp.http.Content-Type = "text/html; charset=utf-8";
    synthetic( {"<!DOCTYPE html>
    <html>
      <head>
        <title>Service Temporarily Unavailable</title>
        <style>
          body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
          h1 { color: #e74c3c; }
          p { font-size: 18px; }
        </style>
      </head>
      <body>
        <h1>We're experiencing technical difficulties</h1>
        <p>Our team has been notified and we're working to restore service.</p>
        <p>Please try again shortly.</p>
      </body>
    </html>"} );
    return (deliver);
}

For dynamic content in your error page, consider these approaches:


sub vcl_backend_error {
    set beresp.http.Content-Type = "text/html; charset=utf-8";
    synthetic( {"<!DOCTYPE html>
    <html>
      <head>
        <title>"} + "Error " + beresp.status + {" | "} + std.tolower(req.http.host) + {"</title>
        <style>body { background: #f8f9fa; }</style>
      </head>
      <body>
        <div>
          <h2>Error "} + beresp.status + {"</h2>
          <p>Request ID: "} + req.xid + {"</p>
        </div>
      </body>
    </html>"} );
    return (deliver);
}

After updating your VCL:

  1. Reload Varnish: sudo systemctl reload varnish
  2. Test by intentionally making your backend unavailable
  3. Check response headers with: curl -I yourdomain.com

Keep error pages lightweight (under 10KB) since they'll be served during high-traffic incidents. Avoid external resources that might fail to load during outages.


When Varnish encounters a backend failure, it serves the infamous "Guru Meditation" error page. While humorous, this default page provides poor user experience and doesn't match professional website standards. Here's how to replace it with a custom HTML page.

The solution involves modifying your Varnish Configuration Language (VCL) file. Here's the essential code snippet:


vcl 4.1;

sub vcl_backend_error {
    if (beresp.status == 503) {
        synthetic({"<!DOCTYPE html>
        <html>
        <head>
            <title>Service Temporarily Unavailable</title>
            <style>
                body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
                h1 { color: #d9534f; }
            </style>
        </head>
        <body>
            <h1>503 Service Temporarily Unavailable</h1>
            <p>We're currently performing maintenance. Please check back soon.</p>
            <p>Error: "} + beresp.status + " " + beresp.reason + {"</p>
        </body>
        </html>"});
        return (deliver);
    }
}

For more sophisticated implementations, consider these enhancements:


sub vcl_backend_error {
    set beresp.http.Content-Type = "text/html; charset=utf-8";
    
    # Different pages for different error scenarios
    if (bereq.url ~ "^/api/") {
        synthetic({"<!-- API-specific error page -->"});
    } else {
        synthetic({"<!-- Standard error page -->"});
    }
    
    # Include retry-after header when appropriate
    set beresp.http.Retry-After = "300";
}

To verify your custom error page:


# Restart Varnish
systemctl restart varnish

# Force a 503 error for testing
varnishadm backend.set_health default sick

Remember to check your Varnish logs after implementing changes:


varnishlog -g request -q "RespStatus == 503"