Setting up Varnish with Virtualmin – CentOS in 5 steps

When working on high-traffic website or even medium-traffic site on a low-end VPS, we will need to find a way to serve traffic effectively. Using Vanish to cache the page content is a good idea to reduce the server load. This tutorial discuss about how to setup varnish with virtualmin on CentOS.

varnish diagram

I have just finished setting up Varnish and my test server that uses Webmin/Virtualmin, with Apache

It has been a little bit of a voyage of discovery but I think I have cracked it. Much of what I have here is based on many other blogs and forums. In essence once you know how its easy, but there are a few pit holes to watch for in Virtualmin/Webmin, as editing the underlying httpd.conf file isn’t the way to go.

The main steps are

  1. Get Varnish
  2. Set up the Varnish control file
  3. Modify the Apache virtual hosts port number
  4. Restart the servers
  5. Tidy up Virtualmin server templates and make sure that Varnish runs on boot / restarted with Apache

and you are done.  My experience is on a Centos server, I’m sure that the process is the same on Ubuntu except the details of some of the linux level commands and file locations

1. Get Varnish

The easy way – from a repository

[bash]rpm –nosignature -i http://repo.varnish-cache.org/redhat/varnish-3.0/el6/noarch/varnish-release/varnish-release-3.0-1.el6.noarch.rpm
yum install varnish[/bash]

2. Set up the Varnish control file & process defaults

In essence to get up and running this is simply putting the port and IP address that Apache will be listening on.

Normally Apache listens on the http port 80, but as Varnish sits in front of Apache, Apache and Varnish will listen on 80 apache has to move – the ‘default’ documentation moves Apache to 8080.

Some people write that they can set it up with Apache listening on 127.0.0.1:80 and Varnish on myexternalIP:80  but I couldn’t get this to work and wasted much time trying to work out where the conflict comes from. If you don’t want to waste time stick to 80 and 8080.

The default.vcl is in /etc/varnish

There are a lot more advanced VCL things that you might have to do, like excluding some virtual hosts, and passing through the originators IP address (that Varnish looses as it is a proxy) I’ll cover them in my ‘advanced’ VCL musing in a later post.

You may will need to go into /etc/sysconfig/varnish  and set the listen port. It is recommended to use the advanced option 2 (remember to comment other options if not used). Example part of file is as follows:

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

In the /etc/varnish/default.vcl, remember to set the host to the IP address if Apache is listening based on IP address, otherwise, Apache will not accept forward content to it. Sample configuration:

[bash]backend default {
.host = "YOUR_SERVER_IP";
.port = "8080";
.connect_timeout = 1s;
.first_byte_timeout = 5s;
.between_bytes_timeout = 2s;
}[/bash]

3. Modify the Apache configuration to use 8080

All the advice points to updating /etc/httpd/conf/httpd.conf. But if you are running Virtualmin/Webmin -> stop – don’t do that.

You have to modify things via Virtualmin or you will get problems later.

It took a while to find

Virtualmin>[server]>Server Configuration>Change IP address and change the ‘New HTTP Port’ from 80 to 8080. Do this for every existing virtual server

If you have a lot, then you can do this at command level, I wrote this script that goes through all virtual server and changes the port to 8080

[bash]for dom in `virtualmin list-domains –with-feature web –name-only`; do
virtualmin modify-web –domain $dom –port 8080
done[/bash]

You then just need to make sure that apache isn’t also listening on port 80.

Go to Webmin>Servers>Apache Webserver, scan down the list of existing Virtual Servers they should all be 8080, the switch to the Global configuration tab > Networking and Addresses, under ports if the is an entry with 80 remove it (none and blank) and save, port 80 shouldn’t be mentioned here at all.

4. Restart The Servers

Sounds simple. I tend to prefer stopping and starting servers at command level. You just need to make sure you stop apache, start varnish and then start apache

[bash]service httpd stop
service varnish start
service httpd start[/bash]

If httpd doesn’t start then its because it is still listening to post 80, or you didn’t change the varnish default.vcl from 80 to 8080

Check you sites are running!

You also might want to see if varnis is actually running and doing something – a couple of command line commands to run woudl be varnishlog and varnishstat. I might post a bit more about mnitoring when I get more familiar with it.

5. Tidy up Virtualmin server templates and make sure that Varnish runs on boot / restarted with Apache

When you create new virtual servers it uses a server template, and if you don’t change the values you will create new virtual servers on port 80 which will create issues.

Virtualmin>Server Templates> edit each template / template section = Apache website, change Port number for Virtual Hosts to 8080

You need to make sure that Varnish start on reboot too, so

Webmin>System>Bootup and Shutdown

scroll down to find Varnish, edit and set it to start on boot

And you will also need to ensure that Varnish is restarted after you restart Apache for any reason (well you may get away with not, but I think it is safer)

Webmin>Servers>Apache Webserver

follow the top link to module config and the pull down, system configuration  and modify the command to start Apache from  /etc/rc.d/init.d/httpd start    to /etc/rc.d/init.d/httpd start;/etc/init.d/varnish restart

and the same for the command to apply after configuration.

That should do it!

Reference: http://badlywired.com/technical-stuff/2013/09/27/setting-up-varnish-with-virtualmin-centos-in-5-steps/

Benchmark result

0. Server specs: a OpenVZ VPS with the following configuration

  • RAM: 2GB
  • 4 CPU cores, Intel(R) Xeon(R) CPU E5-2620 @ 2.00GHz
  • HTTP server: Apache
  • PHP 5.3.x/5.4.x
  • MySQL 5.5
  • Several WordPress blogs with each has 200 posts (quite small :-))

1. Before Varnish is installed

[bash][[email protected] ~]# ab -n 1000 -c 50 http://blog.abc.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking blog.abc.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests

Server Software: Apache/2.2.15
Server Hostname: blog.abc.com
Server Port: 80

Document Path: /
Document Length: 38012 bytes

Concurrency Level: 50
Time taken for tests: 7.494 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 38361712 bytes
HTML transferred: 38075140 bytes
Requests per second: 133.44 [#/sec] (mean)
Time per request: 374.687 [ms] (mean)
Time per request: 7.494 [ms] (mean, across all concurrent requests)
Transfer rate: 4999.18 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 8 8 0.6 8 17
Processing: 56 361 240.5 263 2342
Waiting: 41 345 240.5 246 2326
Total: 64 369 240.5 271 2350

Percentage of the requests served within a certain time (ms)
50% 271
66% 370
75% 391
80% 401
90% 487
95% 1002
98% 1257
99% 1349
100% 2350 (longest request)
[/bash]

2.  After Varnish is installed

[bash][[email protected] ~]# ab -n 1000 -c 50 http://blog.abc.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking blog.abc.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests

Server Software: Apache/2.2.15
Server Hostname: blog.abc.com
Server Port: 80

Document Path: /
Document Length: 38012 bytes

Concurrency Level: 50
Time taken for tests: 2.001 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 38581155 bytes
HTML transferred: 38185865 bytes
Requests per second: 499.66 [#/sec] (mean)
Time per request: 100.069 [ms] (mean)
Time per request: 2.001 [ms] (mean, across all concurrent requests)
Transfer rate: 18825.48 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 8 26 129.4 8 1021
Processing: 24 56 89.5 26 715
Waiting: 8 20 41.5 9 635
Total: 32 82 158.8 35 1273

Percentage of the requests served within a certain time (ms)
50% 35
66% 38
75% 43
80% 48
90% 257
95% 275
98% 720
99% 1038
100% 1273 (longest request)
[/bash]

Troubleshoot

  1. If facing the error “Error 503 Service Unavailable” quite frequently (especially when updating wordpress via auto-update), try to increase timeout value:[bash]backend default {
    .host = "XXX.XXX.XXX.XXX";
    .port = "YOUR_PORT";
    .connect_timeout = 5s;
    .first_byte_timeout = 10s;
    .between_bytes_timeout = 10s;
    }[/bash]

Leave a Reply