fbpx

Server Setup

Deployment and cache purge on Citrus powered servers

by , , revisited on


We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.

Citrus is what we internally call the web software stack of Varnish, Nginx, PHP-FPM and Percona MySQL.

To invalidate PHP OPcache, without restarting PHP-FPM, you want to use cachetool.
The latest branch of cachetool only supports the most recent PHP versions.

Branch 3.x of cachetool supports many PHP versions (5.5 onward, including PHP 7).
To install it:

sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
sudo yum -y install cachetool

Often times, due to a number of caching layers, the changes to website files do not reflect on the site immediately or do not reflect at all. This is a good thing, aimed to ease the load to PHP backend and increase performance and total traffic throughput.

The caching layers may include:

  • PHP opcode cache. The production setting for revalidate_timestamps will cause old versions of PHP files to be in use until a call to opcache_reset()
  • Varnish cache. Varnish cache will store PHP-generated HTML. Supporting CMS (WordPress, Magento) will automatically communicate with Varnish in order to invalidate its cache. In some scenarios though (themes files changes) a manual cache purge is required

A simple GitHub hook for deployment and cache clearing may look like this:

<?php

// Github will post secret code to your hook script and we have to check for it
if (!isset($_GET['code']) && $_GET['code'] != 'replace-me-with-random-password') {
        exit('404');
}

$result = exec('git pull') 
        . exec('../artisan migrate') 
        . exec('cd ../ && composer install') 
        . exec('curl -X PURGE -H "User-Agent: W3 Total Cache/.*" http://www.example.com/.*')   
        . opcache_reset()
        . clearstatcache(true);

Script logic

git pull fetches files from remote git origin.

../artisan migrate runs database migrations for Laravel website.

cd ../ && composer install for a site using Composer and not tracking track vendor directory in git, install PHP libraries

curl -X PURGE -H "User-Agent: W3 Total Cache/.*" http://www.example.com/.*' This will purge complete cache for domain in Varnish

clearstatcache(true) clears real path PHP cache

Finally, opcache_reset() clears PHP opcode cache

Branch-based development

You may also have set up staging and master branches on respective domains. Your deployment hook can be able to act only when a specific branch is being merged.
For this, you can use branch named passed in the web hook, e.g. provided by BitBucket:

if ($payload && $branch == $payload->push->changes[0]->new->name) {

A further improvement may be putting up all the clear and deployment commands in a single deploy.sh file which is run by the webhook in the background.
So you can set up a $branch variable that is obtained either from shell environment or included from a gitignored file. Its value may be staging or master to match up with the git branch having been pushed to:

if ($payload && $branch == $payload->push->changes[0]->new->name) {
    $deployCmd = 'deploy.sh';
    exec('bash -c "exec nohup setsid ./' . $deployCmd . ' > ./deploy.log 2>&1 &"');
}

This truly detaches from any SSH sessions and runs $deployCmd in the background.

The deploy.sh may look like the following for a Magento 1.x website:

#!/bin/bash

/usr/bin/git pull
/usr/local/bin/cachetool stat:clear
/usr/local/bin/cachetool opcache:reset
n98-magerun cache:flush

Some things are important to remember:

The URL in Varnish cache purge should be plain HTTP, not HTTPS since communication to Varnish always happens over HTTP.
The call to opcache_reset() should only be done in a webhook and not directly on the command line. Calling it directly on the command line will not affect opcache data of PHP-FPM pools and thus the cache will stay intact.

If you want to clear PHP opcache and realpath caches on the command line, use the following:

/usr/local/bin/cachetool opcache:reset
/usr/local/bin/cachetool stat:clear

For a complete integration, take a look at GitHook.

Purge cache in Prestashop

<?php

chdir(dirname(__FILE__));

echo 'Clearing File Cache' . '<br />';
shell_exec('rm -rf ./cache/cachefs');

echo 'Clearing Smarty Caches' . '<br />';
shell_exec('rm -rf ./cache/smarty/cache');
shell_exec('rm -rf ./cache/smarty/compile');
shell_exec('rm -rf ./cache/class_index.php');

echo 'Clearing filestat cache' . '<br />';
clearstatcache();
clearstatcache(true);

echo 'Clearing PHP files cache (opcache)' . '<br />';
opcache_reset(); 

require_once 'config/settings.inc.php';

echo 'Clearing smarty cache database tables' . '<br />';

/* Connect to a MySQL database using driver invocation */
$dsn = 'mysql:dbname=' . _DB_NAME_ . ';host=' . _DB_SERVER_;

try {
    $conn = new PDO($dsn, _DB_USER_, _DB_PASSWD_);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

$conn->query(sprintf("TRUNCATE TABLE %ssmarty_cache", _DB_PREFIX_));
$conn->query(sprintf("TRUNCATE TABLE %ssmarty_last_flush", _DB_PREFIX_));
$conn->query(sprintf("TRUNCATE TABLE %ssmarty_lazy_cache", _DB_PREFIX_));

echo 'Done';

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.