Mercury on Ubuntu 10.04 (Lucid)

This high performance Drupal system is based on the work of Project Mercury. Project Mercury aims to increase the performance and ability of Drupal powered websites to respond to increased load. This document leverages the same collection of popular open source tools including the Varnish Accelerating Proxy, the APC bytecode cache for PHP, Memcached for accelerating database operations, and the Solr search engine. These instructions modify the Drupal community instructions for Project Mercury for use with the Linode Platform and the 10.04 release of the Ubuntu Distribution.

You may also choose to deploy your high performance Drupal stack with Linode's StackScript. Simply click on the "Deploy using StackScripts" link on the "Deploy a Linux Distribution" page. When the new Linode boots your system will be running Pantheon Project Mercury. Note that both the StackScript edition and the version of Mercury described in this document require substantial system resources; ensure your system has at least 512 megabytes of RAM. Additionally, at the time of initial publication, be aware that many Drupal Modules may not be fully compatible with PHP version 5.3 that ships with Lucid. Prior to beginning this guide for installing the high performance stack based on Project Mercury, we assume that you have completed our getting started guide. If you're new to Linux systems administration we recommend engaging the guides in our using Linux guide series, particularly the administration basics guide.

Set the Hostname

Before you begin installing and configuring the components described in this guide, please make sure you've followed our instructions for setting your hostname. Issue the following commands to make sure it is set properly:

hostname -f

The first command should show your short hostname, and the second should show your fully qualified domain name (FQDN).

Install Software

Before installing this software, you must enable the universe, multiverse, and restricted repositories. Your /etc/apt/sources.list file will resemble the following:


## main & restricted repositories
deb lucid main restricted
deb-src lucid main restricted

deb lucid-updates main restricted
deb-src lucid-updates main restricted

deb lucid-security main restricted
deb-src lucid-security main restricted

## universe repositories - uncomment to enable
deb lucid universe
deb-src lucid universe

deb lucid-updates universe
deb-src lucid-updates universe

deb lucid-security universe
deb-src lucid-security universe

## multiverse repositories
deb lucid multiverse
deb-src lucid multiverse

deb lucid-updates multiverse
deb-src lucid-updates multiverse

deb lucid-security multiverse
deb-src lucid-security multiverse

Issue the following commands to ensure that your system's package database is brought up to date and that all installed software is running the latest released version:

apt-get update
apt-get upgrade

Issue the following command to install all required software:

apt-get install apache2 tomcat6 apache2-mpm-prefork apache2-utils apache2.2-common autoconf memcached automake automake1.4 autotools-dev bzr defoma fontconfig-config libapache2-mod-php5 libapache2-mod-rpaf libapr1 libaprutil1 libdbd-mysql-perl libdbi-perl libfontconfig1 libfreetype6 libgd2-xpm libhtml-template-perl libjpeg62 libltdl7 libltdl7-dev libmysqlclient16 libnet-daemon-perl libplrpc-perl libpng12-0 libpq5 libssl-dev libt1-5 libtool libvarnish1 libxpm4 m4 mysql-common mysql-server mysql-client php-apc php5 php5-cli php5-curl php5-common php5-dev php5-gd php5-mysql php5-xmlrpc php-pear postfix shtool ssl-cert subversion ttf-dejavu ttf-dejavu-core ttf-dejavu-extra varnish zlib1g-dev bzr bzrtools php5-memcached

As your package management tool installs the required software, you will be prompted to answer two questions. First, if you have not already installed the MySQL database system, you will be asked for a MySQL root password. This is only the root password for the database and should be different from your system's root password. Second, you you will be asked to configure the Postfix email server. You want to select the "Internet Site" option and then insert the publicly resolvable unique name of the server. You may then proceed with the configuration of the remainder of this system.

Configure System Components

Project Mercury isn't a single piece of software that you can install and configure with a single apt-get invocation, but rather a collection of a number of different tools that combine to provide the increases in performance and capability for Drupal sites. The following sections provide instructions for configuring these components.

For the purposes of this document we assume that your Drupal site will be hosted at the domain, and that your virtual hosting file points to a DocumentRoot located at /srv/www/

Install Drush, the Drupal Shell

Drush is a command based interface for manipulating Drupal deployments on your system. Download and install the package by issuing the following commands:

cd /opt/
tar -xvzf drush-All-versions-3.0-beta1.tar.gz
chmod +x /opt/drush/drush
ln -s /opt/drush/drush /usr/bin/drush

Configure Apache

This system uses the Apache HTTP server as an application server rather than as front end web server. Rather than responding to incoming requests on port 80, Varnish will respond to requests on port 80 and proxy these requests back to Apache, which will listen on port 9880 in this case. We need to reconfigure Apache to behave in this manner. First in /etc/apache2/ports.conf modify the Listen and the NameVirtualHost directives to specify port 9880 rather than 80, as in the following example:

File excerpt:/etc/apache2/ports.conf

NameVirtualHost *:9880
Listen 9880

Edit the /etc/apache2/sites-available/default file to modify the default Virtual Host to correspond to the virtual host specified in the NameVirtualHost directive. The first line of this file should resemble:

File excerpt:/etc/apache2/site-available/default

<VirtualHost *:9880>

Issue the following command to enable the mod_rewrite module:

a2enmod rewrite
/etc/init.d/apache2 restart

When you configure or reconfigure the virtual host for the domain where your Drupal site will be hosted, ensure that this virtual host is pointed to the proper port, i.e. 9880. You may not run any services on port 80 of the IP address where Varnish will be running.

Create Apache Virtual Host

Create a virtual host entry in your Apache configuration tree for the site you have created. Consider the following example:

File excerpt:Apache Virtual Host Configuration

<VirtualHost *:9880>

   DocumentRoot /srv/www/

   ErrorLog /srv/www/
   CustomLog /srv/www/ combined

Issue the following command to restart the web server so that all changes can take effect:

/etc/init.d/apache2 restart

Configure Varnish

Because all external requests for your website in this system are handled by Varnish, we need to reconfigure Varnish to listen for requests on port 80. Begin by changing the value of the INSTANCE variable in the /etc/default/varnish file:

File excerpt:/etc/default/


Edit the DAEMON_OPTS settings in the same file to respond to requests under port 80, and to modify the amount of RAM varnish will use. Consider the following example:

File excerpt:/etc/default/varnish

DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/pressflow.vcl \
             -S /etc/varnish/secret \
             -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,135MB"

Above, Varnish will use up to 135 MB of RAM for cache. Project Mercury recommends using 25% of available RAM for Varnish. Modify this number to reflect the amount of RAM you want to dedicate to Varnish. In general, you should give Varnish as much RAM as possible without impinging upon your system's ability to provide other services, including the database and other application services. As this balance may depend on a multitude of factors including load and use patterns, start with a conservative memory usage value and adjust as needed based on system load.

Additionally you will need to create pressflow.vcl file to allow Varnish and Drupal to be able to communicate properly.


backend default {
.host = "";
.port = "9880";
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;

sub vcl_recv {
  // Remove has_js and Google Analytics cookies.
  set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*",

  // To users: if you have additional cookies being set by your system (e.g.
  // from a javascript analytics file or similar) you will need to add VCL
  // at this point to strip these cookies from the req object, otherwise
  // Varnish will not cache the response. This is safe for cookies that your
  // backed (Drupal) doesn't process.
  // Again, the common example is an analytics or other Javascript add-on.
  // You should do this here, before the other cookie stuff, or by adding
  // to the regular-expression above.

  // Remove a ";" prefix, if present.
  set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
  // Remove empty cookies.
  if (req.http.Cookie ~ "^\s*$") {
    unset req.http.Cookie;

  // No varnish for install or update.php
  if (req.url ~ "install\.php|update\.php") {
    return (pass);

  // Normalize the Accept-Encoding header
  // as per:
  if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
      # No point in compressing these
      remove req.http.Accept-Encoding;
    } elsif (req.http.Accept-Encoding ~ "gzip") {
      set req.http.Accept-Encoding = "gzip";
   } elsif (req.http.Accept-Encoding ~ "deflate") {
      set req.http.Accept-Encoding = "deflate";
    } else {
      # unkown algorithm
      remove req.http.Accept-Encoding;

  // Let's have a little grace
  set req.grace = 30s;


// Strip any cookies before an image/js/css is inserted into cache.
// Also: future-support for ESI.
// Disabled pending error resolution
// sub vcl_fetch {
//  if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
//    unset obj.http.set-cookie;
//  }
//  esi;
// }

sub vcl_hash {
  if (req.http.Cookie) {
    set req.hash += req.http.Cookie;

sub vcl_error {
  // Let's deliver a slightly more friedly error page.
  // You can customize this as you wish.
  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"
      <title>"} obj.status " " obj.response {"</title>
      <style type="text/css">
      #page {width: 400px; padding: 10px; margin: 20px auto; border: 1px solid black;
background-color: #FFF;}
      p {margin-left:20px;}
      body {background-color: #DDD; margin: auto;}
    <div id="page">
    <h1>Page Could Not Be Loaded</h1>
    <p>We're very sorry, but the page could not be loaded properly. This should be
fixed very soon, and we apologize for any inconvenience.</p>
    <hr />
    <h4>Debug Info:</h4>
Status: "} obj.status {"
Response: "} obj.response {"
XID: "} req.xid {"
      <address><a href="">Varnish</a></address>

Additionally, issue the following command to ensure that the required directory exists for Varnish's use and to restart the varnish web server:

mkdir -p /var/lib/varnish/pressflow/
/etc/init.d/varnish restart

Configure the APC Accelerator for PHP

APC, the "Alternative PHP Cache," is a bytecode cache for PHP that speeds the execution of PHP code by storing a byte-compiled version of your application in memory for faster execution. Add the following lines to your /etc/php5/conf.d/apc.ini file:

File excerpt:/etc/php5/conf.d/apc.ini
apc.include_once_override = 1

APC can also be configured to not recheck already cached code, for faster implementation. This can provide a significant performance boost in production environments , but is not desirable for systems where the PHP code is changing regularly. If you wish to enable this setting, add the following value to the /etc/php5/conf.d/apc.ini file:

File excerpt:/etc/php5/conf.d/apc.ini

apc.apc.stat = 0

Install Pressflow

Project Mercury is based around a distribution of the Drupal content management system called "Pressflow," which is optimized to provide a Drupal system that is more resilient to higher demand situations. Issue the following sequence of commands. This will remove the entire contents of your DocumentRoot. Only issue this command sequence if there is nothing of worth in the /srv/www/ directory.

rm -rf /srv/www/
bzr branch lp:pressflow /srv/www/
echo "create database pressflow;" | mysql -u root -p

These commands clear the contents of the DocumentRoot, download a copy of Pressflow into the DocumentRoot using the Bazaar version control system, and create a database for the Pressflow site. Issue the following commands to create the default Pressflow site profile:

cd /srv/www/
mkdir /srv/www/
mv /srv/www/ ./
rmdir /srv/www/
bzr branch lp:pantheon/profiles /srv/www/
mv default /srv/www/

Configure Drupal Components

Download Drupal Modules with Drush

Use the drush tool to install the Varnish, Memcache, and related modules for Drupal, which will allow your Drupal instance to take full advantage of these services:

drush dl --destination=/srv/www/ memcache-6.x-1.x-dev
drush dl --destination=/srv/www/ varnish
drush dl --destination=/srv/www/ cacherouter
drush dl --destination=/srv/www/ apachesolr

Issue the following sequence of commands to install the Apache Solr module and ensure that the proper permissions have been set on your files:

cp /srv/www/ /srv/www/
mkdir -p /srv/www/
cd /srv/www/
svn checkout -r22 SolrPhpClient
mv /srv/www/ /opt/solr/conf/
mv /srv/www/ /opt/solr/conf/
chown -R root:www-data /srv/www/*
chmod -R 775 /srv/www/
chmod 755 /srv/www/

Complete Drupal Installation Process

You may now visit your Drupal instance in your web browser at the address Select the "Mercury" installation profile, and enter your database credentials at this juncture. When this process is complete, issue the following commands to modify the permissions of your Drupal files as required by the Drupal system:

chmod -R 755 /srv/www/
chmod g+w /srv/www/

Once the database is configured, return to this document before beginning to use this Drupal instance as various components of Drupal and Mercury require additional configuration.

Edit Drupal Settings File

Add or edit the following values in the default settings.php for your Pressflow/Drupal instance, which will make it possible for your site to work with memcache and varnish.

File excerpt:/srv/www/

# Varnish reverse proxy on localhost
$conf['reverse_proxy'] = TRUE;
$conf['reverse_proxy_addresses'] = array('');

# Memcached configuration
$conf['cache_inc'] = './sites/all/modules/memcache/';
$conf['memcache_servers'] = array(
         '' => 'default',
         '' => 'menu',
         '' => 'filter',
         '' => 'form',
         '' => 'block',
         '' => 'update',
         '' => 'views',
         '' => 'content',
         '' => 'apachesolr',
$conf['memcache_bins'] = array(
          'cache'        => 'default',
          'cache_menu'   => 'menu',
          'cache_filter' => 'filter',
          'cache_form'   => 'form',
          'cache_block'  => 'block',
          'cache_update' => 'update',
          'cache_views'  => 'views',
          'cache_views_data'  => 'views',
          'cache_content'  => 'content',
          'cache_apachesolr'  => 'apachesolr',

Enable and Configure Drupal Modules with Drush

You may enable all of the modules installed above using drush by issuing the following command:

cd /srv/www/
drush en apachesolr apachesolr_search search cacherouter

Issue the following drush commands to search settings for Apache Solr:

cd /srv/www/
drush vset --yes apachesolr_port 8080;
drush vset --yes apachesolr_cron_limit 50;
drush vset --yes apachesolr_search_make_default 1;
drush vset --yes apachesolr_search_spellcheck 1;
drush vset --yes search_cron_limit 50

Issue the following set of drush commands to optimize Drupal's caching and to allow it to interoperate with the Varnish cache:

cd /srv/www/ drush vset –yes cache 3; drush vset –yes cache_lifetime 0; drush vset –yes page_cache_max_age 600; drush vset –yes block_cache 1; drush vset –yes preprocess_css 1; drush vset –yes preprocess_js 1; drush vset –yes page_compression 0;

Finally, create the following cron job by placing the following line in a /etc/cron.d/drupal file:


0 * * * * root /usr/bin/wget -O - -q -t 1

This will allow Drupal to run a set of regular tasks every hour for search indexing and other important Drupal maintenance. You will want to restart Tomcat to make it possible for Drupal to communicate with the Solr instance by issuing the following command:

/etc/init.d/tomcat6 restart

Congratulations! You have successfully installed and configured all of the components of a high performance Drupal setup! You may now visit your site at to view and modify your site.

More Information

You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.