💾 Archived View for chirale.org › 2015-04-01_1249.gmi captured on 2024-08-31 at 12:00:48. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2024-05-12)

-=-=-=-=-=-=-

Clear Varnish cache via PHP: a Drupal 7 proof of concept

Using Varnish as reverse proxy or proxy is an useful approach to reduce the load of webservers like Apache.

In Drupal 7 I’ve to clear the varnish cache of a specific domain when Drupal caches are globally cleared. Drupal has the right hook invoked when cache are cleared:

 function clearcachevarnish_flush_caches() { $filename = '/var/www/varnishdomains2cleardir/varnishdomains2clear'; // each domain on a separate line: append to the end of the file $myfile = fopen($filename, "a"); $h = $_SERVER['HTTP_HOST']; $txt = $h . "\n"; fwrite($myfile, $txt); fclose($myfile); drupal_set_message('Varnish cache queued to be cleared. Please wait 1 minute before checking.'); // no cache table should be cleared return array(); } 

Now this piece of code simply adds the current domain to a ASCII text file on /var/www/varnishdomains2cleardir/varnishdomains2clear.

Preparing the file to the write

On CentOS you have to add /var/www/varnishdomains2cleardir to the httpd-writable directories list using:

 mkdir /var/www/varnishdomains2cleardir; chcon -v --type=httpd_sys_content_t /var/www/varnishdomains2cleardir; chown myuser:mygroup /var/www/varnishdomains2cleardir; chmod -R 777 /var/www/varnishdomains2cleardir; touch /var/www/varnishdomains2cleardir/varnishdomains2clear; 

Now the empty file is ready to be written by your hook_flush_caches() implementation. Now enable the clearvarnishcache module and clear the cache to write the current domain name to the file.

hook_flush_caches()

The clear varnish cache script

To clear the varnish cache you usually have to be logged as root using the command varnishadm. Here a script that will read the domains file written above, clear the varnish cache for that domain and then remove the domains lines.

varnishadm

 #!/bin/bash callinguser=`whoami` if [ "root" != "$callinguser" ] then echo "Only root can run this command." exit 1 fi cd /path/to/clear/cache/command/ date=`date +%Y-%m-%d_%H:%M:%S` # check lock # prevent the script from being run more than once if [ -f /tmp/clearcachevarnish-lock ]; then echo "Script clearcachevarnish is already running. You can rm /tmp/clearcachevarnish-lock to break the lock manually." exit 1 fi touch /tmp/clearcachevarnish-lock dominidapulire=`less /var/www/varnishdomains2cleardir/varnishdomains2clear` while [[ ! -z $dominidapulire ]] do dominio=$(echo "$dominidapulire" | sed -n '$p') echo $dominio dominidapulire=$(echo "$dominidapulire" | sed '$d') if [ "" != "$dominio" ] then varnishadm -T 1:6082 -S /etc/varnish/secret ban req.http.host == "$dominio" echo "varnish cleared on $dominio" fi done # remove all domains lines truncate --size 0 /var/www/varnishdomains2cleardir/varnishdomains2clear # remove lock rm /tmp/clearcachevarnish-lock 

Make this script as executable .sh file using chmod a+x on it. If you run the bash script, varnish cache for files on the domains list will be cleared. It’s not so useful when using the Drupal UI so we should schedule this task periodically, e.g. every minute.

Scheduling the varnish clear cache

Here the crontab entry for execute the script every minute:

 all.sh django2gmi.sh processing README.md wp2gmi.sh all.sh django2gmi.sh processing README.md wp2gmi.sh all.sh django2gmi.sh processing README.md wp2gmi.sh all.sh django2gmi.sh processing README.md wp2gmi.sh all.sh django2gmi.sh processing README.md wp2gmi.sh root /path/to/clear/cache/command/clearcachevarnish.sh 

The steps

User clear Drupal cache hook_flush_caches() is invoked: the domains list file is written clear varnish cache script is launched by root every minute for each domain in the list, varnish cache is cleared

hook_flush_caches()

This is the end of this proof of concept. The code wasn’t tested against attacks so please comment if you have any suggestion to improve it. I’m not very fond of the idea of a php script writing something read by a bash script but this is the less problematic solution I found for this case.

https://web.archive.org/web/20150401000000*/https://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_flush_caches/7

https://web.archive.org/web/20150401000000*/https://www.varnish-cache.org/docs/3.0/reference/varnishadm.html

https://web.archive.org/web/20150401000000*/https://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_flush_caches/7