14

We are using Varnish at the front of Plone. In the case Plone goes down or serves an internal error we'd like to show a user-friendly static HTML page which some CSS styling + images. ("The server is being updated page")

How to configure Varnish to do this?

Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435

4 Answers4

21

Another simple way to do it is using the std vmod that comes with varnish. This is my preferred way to do it because I like having the error messages outside the configuration in case you want to have multiple responses for different status codes.

import std;

sub vcl_error {
    set obj.http.Content-Type = "text/html; charset=utf-8";
    synthetic std.fileread("/path/to/file.html");

    return (deliver);
}
bwight
  • 3,300
  • 17
  • 21
15

You can customize the synthetic page being served on a vlc_error. The default.vcl configuration file already shows how to do this, by serving the famous "Guru Meditation" error page (ahh, those wonderful Amiga days).

An example customization:

    sub vcl_error {
        set obj.http.Content-Type = "text/html; charset=utf-8";
        synthetic {"
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
      <head>
        <title>Sorry, server under maintainance - My Website"</title>
        <style src="css/style.css"></style>
      </head>
      <body>
        <h1>The server is being updated</h1>
        <p>Please check back later. Meanwhile, here's a picture of a rabbit with a pancake on its head:</p>
        <img src="img/wabbit.jpg" alt="awwwww!" />
      </body>
    </html>
    "};
    return (deliver);
}
Community
  • 1
  • 1
Rigel Di Scala
  • 3,150
  • 2
  • 17
  • 23
  • 5
    This makes the assumption that css/style.css and img/wabbit.jpg will be available if the backend server is down. While you can use a similar synthetic to serve the CSS file, Varnish does not yet have binary strings in VCL so serving the wabbit.jpg is not going to be possible. Some browser support inline base64 encoded data urls, but by no means all, so you might need to direct requests at a backup static server, or reference images / resources on another server (Amazon S3 might be a good choice for that.) – Laurence Rowe May 14 '11 at 13:24
5

There isn't much help for doing this with Varnish 4 at the moment.

Here is what I ended up with:

sub vcl_backend_error {
    set beresp.http.Content-Type = "text/html; charset=utf-8";
    synthetic(std.fileread("/var/www/errors/500.html"));
    return (deliver);
}

For more info see the upgrading to 4.0 docs.

Tom Holder
  • 311
  • 4
  • 5
2

If you rather prefer to deliver an error page from a static file, you can override vcl_error() with a bit of C-code:

sub vcl_error {
    set obj.http.Content-Type = "text/html; charset=utf-8";

    C{
        #include <stdio.h>
        #include <string.h>

        FILE * pFile;
        char content [100];
        char page [10240];
        char fname [50];

        page[0] = '\0';
        sprintf(fname, "/var/www/error/index.html", VRT_r_obj_status(sp));

        pFile = fopen(fname, "r");
        while (fgets(content, 100, pFile)) {
            strcat(page, content);
        }
        fclose(pFile);
        VRT_synth_page(sp, 0, page, "<!-- XID: ", VRT_r_req_xid(sp), " -->", vrt_magic_string_end);

        return (deliver);
    }C
}
simcen
  • 119
  • 1
  • 1
  • 5
  • 3
    That's some pretty nasty C. Better hope your error page content is smaller than 100 characters. – Jon Topper Aug 03 '12 at 18:00
  • 3
    His code accepts any file up to 10240 characters. It reads the file in to a 100 buffer until it reaches the end of the file. I agree though, pretty nasty C. – bwight Jan 23 '13 at 21:32
  • 3
    First time I see `text/html; charset=utf-8` so close to `#include ` and it doesn't feel comfortable. – cherouvim Jul 19 '13 at 13:52