Adding Varnish Cache to Ghost Blog

Self-Hosting Jun 16, 2021

Introducing Varnish - Thanks Fastly

Big shoutout to for recently taking half the internet offline (BBC News Aritcle). Resulting in some free advertising for Varnish an open source caching server.

I instantly thought, would Varnish be a solution to decrease load times and handle traffic peaks?

Skip to the setup guide here

The Setup

The new setup includes a Varnish server which has been deployed using docker. This is positioned between Caddy (Reverse Proxy) and Ghost. Varnish is used to cache a wide range of static content on the page such as Javascript, CSS and text files. As the HTML is not being cached this allows the site to stay dynamic.
Varnish Setup Diagram


To benchmark the performance of the site I'll be using This loads in the entire site as if were in the browser. I ran 4 tests in both London and Washington, 2 with Varnish enabled and 2 without.

Varnish Test Location Load Time
London, UK 548 ms
London, UK 546 ms
London, UK 623 ms
London, UK 721 ms
Washington D.C 1260 ms
Washington D.C 1130 ms
Washington D.C 1420 ms
Washington D.C 1380 ms

Set it up yourself

First, ensure you have docker and docker-compose installed.

Use the following docker-compose template:

version: '3.1'

    image: varnish:stable
    container_name: varnish
    restart: unless-stopped
     - ./default.vcl:/etc/varnish/default.vcl
      name: dockernet

Then create the Varnish config file nano default.vcl:

vcl 4.0;

backend default {
    .host = "<GHOST-IP>:2368";
sub vcl_recv {
    # Do not cache the admin and preview pages
    if (req.url ~ "/(admin|p|ghost)/") {
           return (pass);
sub vcl_backend_response {
    if (beresp.http.content-type ~ "text/plain|text/css|application/json|application/x-javascript|text/xml|application/xml|application/xml+rss|text/javascript") {
        set beresp.do_gzip = true;
        set beresp.http.cache-control = "public, max-age=1209600";

Spin it up: sudo docker-compose up -d

Now just point Caddy at the varnish server.
Example config: {