Install Pressflow (Drupal), Varnish, APC and Apache on CentOS 5.5

Submitted by Janak on Sat, 09/25/2010 - 13:50

After having run website on Drupal 6 with Apache+PHP+MySql, I wanted to move to Pressflow so I could harness the added advantages of Varnish.

This is not an in-depth installation guide or a discussion about Varnish or Pressflow, but quick setup commands for my own reference. Please see links at the end if you wish to explore Varnish or Pressflow setup in greater depth.

I wanted:
Varnish > APC > Apache > Pressflow setup..

Here is what I did:

Install Apache

yum install httpd

For a detailed installation tutorial, please see:…

Configure Apache to run on port 8080

sudo nano /etc/httpd/conf/httpd.conf

edit the httpd.conf file to allow apache to run on port 8080

Listen 8080
NameVirtualHost *:8080

Reconfigure all my VHosts to run on port 8080

nano /etc/httpd/conf.d/1_varnish.conf

Disable proxy_ajp file

mv /etc/httpd/conf.d/proxy_ajp.conf /etc/httpd/conf.d/proxy_ajp.conf_dis

<VirtualHost *:8080>
 DocumentRoot /var/www/html/varnished
 ServerName varnished.local
 ErrorLog /var/log/httpd/varnished_com_error_log
 LogFormat Combined
 TransferLog /var/log/httpd/varnished_com_access_log

Install EPEL Repo

rpm -Uvh

Install Varnish

Varnish is bundled in EPEL Repo

yum install varnish

Auto start varnish

sudo /sbin/chkconfig varnish on --level 2345

Configure Varnish to run on port 80

Varnish setup and config

nano /etc/sysconfig/varnish

DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/varnished.vcl \
             -u varnish -g varnish \
             -s file,/var/lib/varnish/varnish_storage.bin,1G"

Setup Varnish VCL File for Pressflow

Use example VCL config file from and modify to your needs

nano /etc/varnish/varnished.vcl

backend default {
  .host = "";
  .port = "8080";
  .connect_timeout = 600s;
  .first_byte_timeout = 600s;
  .between_bytes_timeout = 600s;
sub vcl_recv {
  if (req.request != "GET" &&
    req.request != "HEAD" &&
    req.request != "PUT" &&
    req.request != "POST" &&
    req.request != "TRACE" &&
    req.request != "OPTIONS" &&
    req.request != "DELETE") {
      /* Non-RFC2616 or CONNECT which is weird. */
      return (pipe);
  if (req.request != "GET" && req.request != "HEAD") {
    /* We only deal with GET and HEAD by default */
    return (pass);
  // Remove has_js and Google Analytics cookies.
  set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+)=[^;]*", "");
  // 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;
  if (req.http.Authorization || req.http.Cookie) {
    /* Not cacheable by default */
    return (pass);
  // Skip the Varnish cache for install, update, and cron
  if (req.url ~ "install\.php|update\.php|cron\.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";
    else {
      # Unknown or deflate algorithm
      remove req.http.Accept-Encoding;
  // Let's have a little grace
  set req.grace = 30s;
  return (lookup);
 sub vcl_hash {
   if (req.http.Cookie) {
     set req.hash += req.http.Cookie;
 // Strip any cookies before an image/js/css is inserted into cache.
 sub vcl_fetch {
   if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
     // This is for Varnish 2.0; replace obj with beresp if you're running
     // Varnish 2.1 or later.
     unset obj.http.set-cookie;
 sub vcl_error {
   // Let's deliver a friendlier 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>

Restart Apache and Varnish

/etc/init.d/httpd restart
/etc/init.d/varnish restart

Further reading:

Configure Varnish for Pressflow
Modules that break caching, and how to fix them
Using Pressflow behind a reverse proxy cache
Example Varnish VCL for a Drupal / Pressflow site
Varnish configuration to only cache for non-logged in users
Varnish best practices
Drupal guide to Managing site performance