We suggest using Drupal with a Varnish reverse proxy. Lagoon provides a
varnish-drupal Docker image that has Varnish already configured with a Drupal Varnish config.
This Varnish config does the following:
- It understands Drupal session cookies and automatically disables the Varnish caching for any authenticated request.
- It automatically caches any assets (images, css, js, etc.) for one month, and also sends this header to the browser, so browser cache the assets as well. This happens for authenticated and non-authenticated requests.
- It has support for
URIBANwhich is used by the Drupal 8 purge module.
- It removes
gclidfrom the URL parameter to prevent Google Analytics links from creating multiple cache objects.
- Many other good things - just check out the drupal.vcl.
Usage with Drupal 8#
TL;DR: Check out the drupal8-advanced example in our examples repo, it ships with the needed modules and needed Drupal configuration.
Note: many of these examples are on the same
drupal-example-simple repo, but different branches/hashes. Be sure to get the exact branch from the examples list!
Install Purge and Varnish Purge modules#
In order to fully use Varnish with Drupal 8 cache tags, you need to install the Purge and Varnish Purge modules. They ship with many submodules. We suggest installing at least the following:
Grab them all at once:
composer require drupal/purge drupal/varnish_purge drush en purge purge_drush purge_tokens purge_ui purge_processor_cron purge_processor_lateruntime purge_queuer_coretags varnish_purger varnish_purge_tags
Configure Varnish Purge#
Configuration > Development > Performance > Purge.
- Add a purger via
Varnish Bundled Purger(not the
Varnish Purger, see the #Behind the Scenes section, for more information.).
- Click the dropdown beside the just added purger and click
- Give it a nice name,
Lagoon Varnishsounds good.
Configure it with:
TYPE: Tag REQUEST: Hostname: varnish (or whatever your Varnish is called in docker-compose.yml) Port: 8080 Path: / Request Method: BAN Scheme: http HEADERS: Header: Cache-Tags Value: [invalidations:separated_pipe]
That's it! If you'd like to test this locally, make sure you read the next section.
Configure Drupal for Varnish#
There are a few other configurations that can be done:
- Uninstall the
Internal Page CacheDrupal module with
drush pmu page_cache. It can cause some weird double caching situations where only the Varnish cache is cleared, but not the internal cache, and changes appear very slowly to the users. Also, it uses a lot of cache storage on big sites.
2628000. This tells Varnish to cache sites for up 1 month, which sounds like a lot, but the Drupal 8 cache tag system is so awesome that it will basically make sure that the Varnish cache is purged whenever something changes.
Test Varnish Locally#
Drupal setups on Lagoon locally have Varnish and the Drupal caches disabled as it can be rather hard to develop with all them set. This is done via the following:
VARNISH_BYPASS=trueenvironment variable in
docker-compose.ymlwhich tells Varnish to basically disable itself.
- Drupal is configured to not send any cache headers (via setting the Drupal config
$config['system.performance']['cache']['page']['max_age'] = 0in
To test Varnish locally, change the following in
falsein the Varnish service section.
docker-compose up -d, which restarts all services with the new environment variables.
Now you should be able to test Varnish!
Here is a short example assuming there is a node with the ID
1 and has the URL
curl -I drupal-example.docker.amazee.io/node/1and look for these headers:
varnishwhich tells you that the request actually went through Varnish.
Age:will be still
0as Varnish has probably never seen this site before, and the first request will warm the varnish cache.
MISS, also telling you that Varnish didn't find a previously cached version of this request.
- Now run
curl -I drupal-example.docker.amazee.io/node/1again, and the headers should be:
Age:will show you how many seconds ago the request has been cached. In our example it will probably something between 1-30, depending on how fast you are executing the command.
HIT, telling you that Varnish successfully found a cached version of the request and returned that one to you.
- Change some content at
curl -I drupal-example.docker.amazee.io/node/1, and the headers should the same as very first request:
Varnish on Drupal behind the scenes#
If you come from other Drupal hosts or have done a Drupal 8 & Varnish tutorial before, you might have realized that there are a couple of changes in the Lagoon Drupal Varnish tutorial. Let's address them:
Varnish Bundled Purger instead of
Varnish Purger purger sends a
BAN request for each cache-tag that should be invalidated. Drupal has a lot of cache-tags, and this could lead to quite a large amount of requests sent to Varnish.
Varnish Bundled Purger instead sends just one
BAN request for multiple invalidations, separated nicely by pipe (
|), which fits perfectly with the Varnish regular expression system of bans. This causes less requests and a smaller ban list table inside Varnish.
Purge Late runtime processor#
Contradictory to the Varnish module in Drupal 7, the Drupal 8 Purge module has a slightly different approach to purging caches: It adds them to a queue which is then processed by different processors. Purge suggests using the
Cron processor , which means that the Varnish cache is only purged during a cron run. This can lead to old data being cached by Varnish, as your cron is probably not configured to run every minute or so, and can result in confused editors and clients.
Instead, we suggest using the
Purge Late runtime processor, which processes the queue at the end of each Drupal request. This has the advantage that if a cache-tag is added to the purge queue (because an editor edited a Drupal node, for example) the cache-tags for this node are directly purged. Together with the
Varnish Bundled Purger, this means just a single additional request to Varnish at the very end of a Drupal request, which causes no noticeable processing time on the request.
Full support for Varnish Ban Lurker#
Our Varnish configurations have full support for
Ban Lurker. Ban Lurker helps you to maintain a clean cache and keep Varnish running smoothly. It is basically a small tool that runs through the Varnish ban list and compares them to the cached requests in the Varnish cache. Varnish bans are used to mark an object in the cache for purging. If Ban Lurker finds an item that should be "banned," it removes them from the cache and also removes the ban itself. Now any seldom-accessed objects with very long TTLs which would normally never be banned and just keep taking up cache space are removed and can be refreshed. This keeps the list of bans small and with that, less processing time for Varnish on each request. Check out the official Varnish post on Ban Lurker and some other helpful reading for more information.
Varnish doesn't cache? Or something else not working? Here a couple of ways to debug:
drush p-debug-ento enable debug logging of the purge module. This should show you debugging in the Drupal log under
- Make sure that Drupal sends proper cache headers. To best test this, use the URL that Lagoon generates for bypassing the Varnish cache, (locally in our Drupal example this is http://nginx-drupal-example.docker.amazee.io). Check for the
Cache-Control: max-age=900, publicheader, where the
900is what you configured in
- Make sure that the environment variable
VARNISH_BYPASSis not set to
docker-compose up -d varnishto make sure the environment variable is configured correctly).
- If all fails, and before you flip your table (╯°□°）╯︵ ┻━┻, talk to the Lagoon team, we're happy to help.