speed up with varnish

Varnish makes your websites fly

….so goes the byline and frankly they’re not lying. I use varnish on atleast 8 websites that do over 200,000 impressions a day. The way it works is actually pretty simple and can be implemented using a plethora of other tools, only varnish does it much more efficiently. Varnish is primarily a website accelerator but it can be configured to work as a high availability load balancer (hell yeah it can beat the pants of any hardware HA load balancer if configured right on the right hardware it can probably do better than an H5). Some of the advertised features

A modern design
VCL – a very flexible configuration language
Load balancing with health checking of backends
Partial support for ESI
URL rewriting
Graceful handling of “dead” backends

The important thing to know is that varnish can be easily dropped in into your cPanel or Plesk managed server and not cause havoc (unlike a lot of opcode caching solutions and other website speedup options). It can probably extend your servers capacity by atleast 50% and much more depending on what percentage of your content is static (images, videos for instance). I’ve used it on practically dead in the water servers, running 150+ sites with 140+ databases, the corresponding zones on named and email with spam/virus scanning for those 150+ sites all off of 2Gb RAM. Moved from 1.83seconds per kb to 0.01kbps, enuf said!!

So in case you’re looking to improve the user experience on your site without investing in improved hardware you should look at varnish as a solution. Also for much less than the cost of owning a hardware load balancer, or a slice of a shared load balancer for that matter, you can setup a software load balancer. Varnish works off one of your webservers alongside the webserver instance and takes the load off of your webserver(s) leaving it free to do the processing for more clients thus expanding your capacity without draining you at the bank.

Before upgrading hardware you’d probably do well to talk to us about setting up your server with Varnish. Please feel free to use the contact form or mail us on [email protected]

varnish with plesk or cpanel

So this is what it is…. if you need help with the setup please use the contact form.

VARNISH
=======
rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
yum install varnish.x86_64 or aptitude install varnish

edit /etc/default/varnish or /etc/sysconfig/varnish — change ports as required
edit /etc/varnish/vcl.conf or /etc/varnish/default.vcl — change backend information

PLESK
=====
/usr/local/psa/admin/sbin/websrvmng –set-http-port –port=80
/usr/local/psa/admin/sbin/websrvmng –reconfigure-all

/etc/init.d/httpd stop
/etc/init.d/varnish start
/etc/init.d/httpd start

cPanel
======
go to tweak settings in WHM and change the port for apache to a non standard one (say 8081)

stop/start apache make sure its listening on new port
start varnish

secure mail (Postfix+SMTP_AUTH+SMTPS — DOVECOT+IMAPS)

This is a quick and dirty on howto enable smtp_auth and ssl encryption for smtp services along with secure imap. I like ot use postfix and dovecot.

INSTALL DOVECOT AND CYRUS-IMAPD
yum install dovecot cyrus-imapd

INSTALL POSTFIX WITH SASL TLS AND CYRUS SUPPORT
wget http://www.tigertech.net/mirrors/postfix-release/official/postfix-2.8.3.tar.gz
tar -zxf postfix-2.8.3.tar.gz
cd postfix-2.8.3
make tidy
make makefiles CCARGS="-DUSE_TLS -DUSE_SASL_AUTH -I/usr/local/include/sasl -DUSE_CYRUS_SASL -I/usr/include/sasl" AUXLIBS="-L/usr/local/lib -lsasl2 -lssl -lcrypto"
make
make install

EDIT /ETC/POSTFIX/MAIN.CF
smtpd_tls_auth_only = no
smtp_use_tls = yes
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = cyrus
local_recipient_maps =
smtpd_use_tls = yes
smtp_tls_note_starttls_offer = yes
broken_sasl_auth_clients = yes
smtpd_tls_key_file = /etc/postfix/ssl/smtpd.key
smtpd_tls_cert_file = /etc/postfix/ssl/smtpd.crt
smtpd_tls_CAfile = /etc/postfix/ssl/cacert.pem
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom

EDIT MASTER.CF
smtps inet n - n - - smtpd
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_sender=yes
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o broken_sasl_auth_clients=yes
-o smtpd_tls_wrappermode=yes

(NOTE: last line is important for supporting buggy clients like outlook express for mac and windows)

GENERATE THE SSL CERTIFICATE
mkdir /etc/postfix/ssl
cd /etc/postfix/ssl/
openssl genrsa -des3 -rand /etc/hosts -out smtpd.key 1024
openssl req -new -key smtpd.key -out smtpd.csr
openssl x509 -req -days 3650 -in smtpd.csr -signkey smtpd.key -out smtpd.crt
openssl rsa -in smtpd.key -out smtpd.key.unencrypted
openssl req -new -x509 -extensions v3_ca -keyout cakey.pem -out cacert.pem -days 3650
openssl pkcs12 -export -in smtpd.crt -inkey smtpd.key -out OutlookSMTP.p12


RELOAD POSTFIX (at this point smtps and smtp_auth are done)

EDIT /ETC/DOVECOT.CONF

protocols = imaps pop3s

protocol imap {
listen = *:143
ssl_listen = *:993
}
protocol pop3 {
listen = *:110
ssl_listen = *:995
}

ssl_disable = no

ssl_cert_file = /etc/pki/dovecot/certs/dovecot.pem
ssl_key_file = /etc/pki/dovecot/private/dovecot.pem

mail_location = mbox:~/mail:INBOX=/var/mail/%u

RELOAD DOVECOT (at this point imaps and pops3 on ports 993 and 995 respectively are enabled)

ensure firewall allows ports 993, 995, 465 are all open.

Varnish + logging + geoip howto

Varnish is the new buzzword making the rounds on the “speed up your website circuit. Does it work? Well suffice to say YMMV…. earlier there was Squid as well as Apache (in reverse proxy mode) so the difference will probably be in how it handles dynamic content and the resources it eats up.

So this one is about how to get geo targetting to work when you have a proxy software caching your static content (and also dynamic content if you set headers in your scripts properly). The way a proxy works is that it sits between your webserver and the visitor. It keeps a store of objects (images, static content etc.) and instead of over burdening your webserver with requests it frees up the task of serving content (or atleast reduces the frequency of requests). All good and happy happy specially for the server admin and moderately for the visitor as well coz response time is slightly reduced.

One of the problems you would face is when you look at your webserver access logs and try to figure out where your traffic is coming from. Since all your traffic is actualy now coming from the proxy you have just one IP in the logs, that of your varnish install. Here you would be advised to change the logformat of your access logs. The way to do that for apache is to set the log format like such:

LogFormat '%{X-Forwarded-For}i %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"' combined

Then make sure that the access log format is set to combined and restart apache. This will start logging the visitors IP instead of the proxy servers address in the access logs and then you can proceed to use your statistics programs as in the pre-proxy era.

For GeoIP also you need to make a few changes. What I use is the php geoip.inc method (keep switching between litespeed, lighttpd, apache depending on what I’m researching at the moment) so instead of mod_geoip the include method works best for me.
So a small change to the code:


include ("geoip.inc");
$headers = apache_request_headers();
$ip = $headers["X-Forwarded-For"];
$gi = geoip_open("/usr/local/share/GeoIP/GeoIP.dat",GEOIP_STANDARD);
$country_code=geoip_country_code_by_addr($gi,$ip);
echo $country_code;

This is using the geoip.inc and the php geoip extension from maxmind.

If you need help with varnish, website tuning, geo targetting or any thing related to linux webserver other than this please contact us

Some things to look at in geoip.inc (if you get the cannot redeclare errors)
replace these two function definitions.

if (!function_exists('geoip_country_code_by_name')){
function geoip_country_code_by_name($gi, $name) {
$country_id = geoip_country_id_by_name($gi,$name);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_CODES[$country_id];
}
return false;
}
}
if (!function_exists('geoip_country_name_by_name')){
function geoip_country_name_by_name($gi, $name) {
$country_id = geoip_country_id_by_name($gi,$name);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_NAMES[$country_id];
}
return false;
}
}

In the vcl for your varnish instance handling the website add this:

sub vcl_pass {

set bereq.http.connection = "close";

if (req.http.X-Forwarded-For) {

set bereq.http.X-Forwarded-For = req.http.X-Forwarded-For;

} else {

set bereq.http.X-Forwarded-For = regsub(client.ip, ":.*", "");

}

}