** At this point, this document is mostly just notes while I repeat the process a few times and make refinements.
From http://getlevelten.com/blog/randall-knutson/create-high-performance-drupal-server-just-30-month
apt-get update
apt-get upgrade
apt-get install emacs vim git-core git-doc rsync unzip patch curl make drush
apt-get install nginx php5-cli php5-mysql php5-fpm php5-cgi php5-gd php5-dev php-pear libpcre3-dev
service nginx start
Place this file in /etc/nginx/sites-available/example.com
server {
listen 8080;
server_name example.com www.example.com;
root /var/www/example.com; ## <-- Your only path reference.
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# This matters if you use drush
location = /backup {
deny all;
}
# Very rarely should these ever be accessed outside of your lan
location ~* \.(txt|log)$ {
deny all;
}
location ~ \..*/.*\.php$ {
return 403;
}
location / {
# This is cool because no php is touched for static content
try_files $uri @rewrite;
}
location @rewrite {
# Some modules enforce no slash (/) at the end of the URL
# Else this rewrite block wouldn't be needed (GlobalRedirect)
rewrite ^/(.*)$ /index.php?q=$1;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors on;
fastcgi_pass unix:/tmp/php-fpm.sock;
#fastcgi_pass 127.0.0.1:9000; # Use this if you didn't change the php-fpm listen.
}
# Fighting with ImageCache? This little gem is amazing.
location ~ ^/sites/.*/files/imagecache/ {
try_files $uri @rewrite;
}
# Catch image styles for D7 too.
location ~ ^/sites/.*/files/styles/ {
try_files $uri @rewrite;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}
Symlink the file to sites-enabled.
cd /etc/nginx/sites-enabled
ln -s ../sites-available/example.com
You may need to bump the memory limit up a bit in php. This depends on how many modules are installed on your site. Next we need to set up some php settings. edit the file /etc/php5/fpm/php.ini
memory_limit: 256M
With the nginx config file we need to set another setting in php.ini
cgi.fix_pathinfo=0
Next we want to switch where php-fpm listens from the IP address to sockets. This is slightly faster and matches the site configuration below.
In /etc/php5/fpm/pool.d/www.conf change
listen = /tmp/php-fpm.sock
Install upload progress and drupal isn't happy without it.
pecl install uploadprogress
Add 'extension=uploadprogress.so' to /etc/php5/fpm/php.ini
sudo apt-get install software-properties-common
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xcbcb082a1bb943db
sudo add-apt-repository 'deb http://sfo1.mirrors.digitalocean.com/mariadb/repo/5.5/ubuntu trusty main'
sudo apt-get update
sudo apt-get install mariadb-server
(from: https://www.varnish-cache.org/installation/ubuntu)
apt-get install apt-transport-https
curl https://repo.varnish-cache.org/ubuntu/GPG-key.txt | apt-key add -
echo "deb https://repo.varnish-cache.org/ubuntu/ trusty varnish-4.0" >> /etc/apt/sources.list.d/varnish-cache.list
apt-get update
apt-get install varnish
(more from: http://getlevelten.com/blog/randall-knutson/create-high-performance-drupal-server-just-30-month)
Now we need to set varnish up to run on port 80 and nginx to run on port 8080.
Edit /etc/default/varnish and change
DAEMON_OPTS="-a :6081 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"
to
DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"
Next create a file at /etc/varnish/default.vcl and put in the following. This one is a generic drupal one that I've created from several sources and have had good luck with.
# A drupal varnish config file for varnish 3.x
#
# Will work with Drupal 7 and Pressflow 6.
#
# Default backend definition. Set this to point to your content
# server. We are assuming you have a web server running on port 8080.
#
backend default {
.host = "127.0.0.1";
.port = "8080";
}
#
sub vcl_recv {
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
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);
}
# Always cache things with these extensions
if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf)$") {
return (lookup);
}
# Do not cache these paths.
if (req.url ~ "^/status\.php$" ||
req.url ~ "^/update\.php$" ||
req.url ~ "^/cron\.php$" ||
req.url ~ "^/install\.php$" ||
req.url ~ "^/ooyala/ping$" ||
req.url ~ "^/admin" ||
req.url ~ "^/admin/.*$" ||
req.url ~ "^/flag/.*$" ||
req.url ~ "^.*/server-status$" ||
req.url ~ "^.*/ajax/.*$" ||
req.url ~ "^.*/ahah/.*$") {
return (pass);
}
## Remove has_js, toolbar collapsed and Google Analytics cookies.
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js|Drupal.toolbar.collapsed|Drupal.tableDrag.showWeight)=[^;]*", "");
## 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;
}
## fix compression per http://www.varnish-cache.org/trac/wiki/FAQ/Compression
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" && req.http.user-agent !~ "MSIE") {
set req.http.Accept-Encoding = "deflate";
} else {
# unkown algorithm
remove req.http.Accept-Encoding;
}
}
# If they still have any cookies, do not cache.
if (req.http.Authorization || req.http.Cookie) {
/* Not cacheable by default */
return (pass);
}
# Don't cache Drupal logged-in user sessions
# LOGGED_IN is the cookie that earlier version of Pressflow sets
# VARNISH is the cookie which the varnish.module sets
if (req.http.Cookie ~ "(VARNISH|DRUPAL_UID|LOGGED_IN)") {
return (pass);
}
return (lookup);
}
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
return (hash);
}
sub vcl_deliver {
# From http://varnish-cache.org/wiki/VCLExampleLongerCaching
if (resp.http.magicmarker) {
/* Remove the magic marker */
unset resp.http.magicmarker;
/* By definition we have a fresh object */
set resp.http.age = "0";
}
#add cache hit data
if (obj.hits > 0) {
#if hit add hit count
set resp.http.X-Varnish-Cache = "HIT";
set resp.http.X-Varnish-Cache-Hits = obj.hits;
}
else {
set resp.http.X-Varnish-Cache = "MISS";
}
return (deliver);
}
The last step is to make sure that the varnish module is downloaded to sites/all/modules and in your drupal settings.php files you have the following:
$conf['cache_backends'][] = 'sites/all/modules/varnish/varnish.cache.inc';
$conf['cache_class_cache_page'] = 'VarnishCache';
$conf['page_cache_invoke_hooks'] = false;
$conf['reverse_proxy'] = true;
$conf['cache'] = 1;
$conf['cache_lifetime'] = 0;
$conf['page_cache_maximum_age'] = 21600;
$conf['reverse_proxy_header'] = 'HTTP_X_FORWARDED_FOR';
$conf['reverse_proxy_addresses'] = array('127.0.0.1');
$conf['omit_vary_cookie'] = true;
For more information on these options, see http://drupal.org/node/1196916
INSTALL MEMCACHE Memcache will improve the performance of php by moving all the caching from sql tables to memory. If you have a lot of logged in users it will help a lot.
Start with some installs
apt-get install memcached libmemcached-tools memstat php5-memcached
Make sure that the memcache module has been downloaded to sites/all/modules and then in your drupal site's settings.php put the following:
$conf['cache_backends'][] = 'sites/all/modules/memcache/memcache.inc'; $conf['cache_default_class'] = 'MemCacheDrupal'; $conf['memcache_key_prefix'] = 'something_unique';