Install Nginx with APC, Varnish, WordPress and W3 Cache on a 128MB VPS

Following on from me trying to fit a WordPress install on a 128MB VPS while not sacrificing performance; I give you my rather comprehensive tutorial on how to install nginx with apc (php opt-code cache), varnish (caching proxy), wordpress and w3 cache.

Introduction

The purpose of this tutorial is to configure a single VPS with 128MB RAM to provide hosting for a single WordPress website by using Nginx as a webserver, MySQL as a database server, PHP-FPM as a fastCGI server, APC as an optcode cache, Varnish as a caching proxy and vsFTPd as a secure FTP server (optional step). I also use openSSH/SCP as the primary means to access the VPS with.

When I write [HOSTNAME] please subsitute everything (incl the brackets) with your hostname (eg. www.example.org).

When I write [USER] please subsitute it (incl the brackets) with your username (eg. example).

In fact, anything [something] please replace with your own values! (eg. [YourPassword]).

I’m running this on my new dedicated server running Proxmox (1.8) with kernel 2.6.32-4-pve and an openVZ debian 6 (32bit) guest, at 128MB RAM and 0MB swap*. This server is running on SSD’s (solid state disks). Running on SSD’s is really nice especially for high iops required to run a VM host.

*) Swap in an openVZ virtual machine is just memory, so 128 RAM + 128 swap would simply mean 256M overall memory. There is no difference. Hence why I just set RAM and not swap for openVZ vms.

Disclaimer

In case you don’t have this set-up, please be aware that you may not get this to work. Caveat emptor – your milage may vary. I suggest you run this on a test bed rather than anything you are using for production already! No warranties are given and no responsibility for time lost, and tears shed assumed. Now make a brew and let’s get on with the show.

Setting up the VPS

Removing stuff

Ref: http://www.lowendbox.com/blog/bootstraping-low-end-vps-with-pre-built-scripts/

We don’t really need rsyslog or portmap, so let’s remove them:

apt-get remove rsyslog portmap

Apt Sources

Adding dot-deb repo

Each line represents a separate command to be executed in sequence!

echo deb http://packages.dotdeb.org stable all >> /etc/apt/sources.list
echo deb-src http://packages.dotdeb.org stable all >> /etc/apt/sources.list
wget http://www.dotdeb.org/dotdeb.gpg
cat dotdeb.gpg | apt-key add -

Adding main debian repos

Each line represents a separate command to be executed in sequence!

echo deb http://mirror.positive-internet.com/debian/ squeeze main non-free contrib >> /etc/apt/sources.list
echo deb-src http://mirror.positive-internet.com/debian/ squeeze main non-free contrib >> /etc/apt/sources.list
echo deb http://security.debian.org/ squeeze/updates main >> /etc/apt/sources.list
echo deb-src http://security.debian.org/ squeeze/updates main >>/etc/apt/sources.list
echo deb http://mirror.positive-internet.com/debian/ squeeze-updates main >> /etc/apt/sources.list
echo deb-src http://mirror.positive-internet.com/debian/ squeeze-updates main >> /etc/apt/sources.list

Updating

apt-get update && apt-get upgrade

Adding base

apt-get install mc sudo iptables curl lsb-release

Adding Varnish repo

Ref: https://www.varnish-cache.org/installation/debian

Each line represents a separate command to be executed in sequence!

curl http://repo.varnish-cache.org/debian/GPG-key.txt | apt-key add -
echo "deb http://repo.varnish-cache.org/debian/ $(lsb_release -s -c) varnish-3.0" >> /etc/apt/sources.list.d/varnish.list
apt-get update
apt-get install varnish

Adding a system user

adduser [USER]

Don’t forget to give your user a password, a strong one preferably.

Add user to sudo

visudo

– find:

root (ALL)

– add below:

[User] (ALL) ALL

Change SSH conf

mcedit /etc/ssh/sshd_config

–find:

PermitRootLogin yes

–change to:

PermitRootLogin no

–find:

X11Forwarding yes

–change to:

X11Forwarding no

–find:

Port 22

–change to:

7742

–add to end:

UseDNS no

 

service ssh restart

Now open a new terminal and connect to your VPS using the username you have chosen and make sure you are connecting to port 7742 and not the default 22! Once logged on, we can continue our journey with installing some software.

Installing Software

apt-get install nginx mysql-server mysql-client memcached php5 php-apc php-auth php-net-smtp php-net-socket php-pear php5-curl php5-gd php5-mcrypt php5-mysql php5-fpm php5-memcached php5-tidy vsftpd

Yes, it was as easy as that! Provided you answered ‘yes’ to the question whether you wanted to install the above and their dependencies, you are now almost done.

Configuring services

OK, I was lying. You are nowhere near done but it’s as good a time as any to make a fresh brew before we dive into configuring our services.

In this section we are setting up the following software:

  • MySQL
  • Nginx
  • PHP5
  • APC
  • FPM
  • memcache
  • Varnish
  • vsFTPd

Configuring MySql

References:
- Reducing MySQL Memory Usage for Low End Boxes
http://www.lowendbox.com/blog/reducing-mysql-memory-usage-for-low-end-boxes/

Each line represents a separate command to be executed in sequence!

mv /etc/mysql/my.cnf /etc/mysql/my.cnf.org
mcedit /etc/mysql/my.cnf

–insert:

[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
language = /usr/share/mysql/english
skip-external-locking
bind-address = 127.0.0.1
thread_stack = 192K
myisam-recover = BACKUP
expire_logs_days = 10
max_binlog_size = 100M
bulk_insert_buffer_size = 8M
connect_timeout=10
interactive_timeout=50
join_buffer=1M
key_buffer=16K
max_allowed_packet=1M
table_cache = 4
max_connect_errors=10
max_connections=100
max_heap_table_size = 8M
myisam_sort_buffer_size=8M
query_cache_limit = 4M
query_cache_size = 250M
query_cache_type = 1
query_prealloc_size = 65K
query_alloc_block_size = 128K
read_buffer_size=1M
read_rnd_buffer_size=768K
record_buffer=1M
safe-show-database
skip-innodb
skip-locking
skip-networking
sort_buffer=64K
thread_cache_size=1024
thread_concurrency=8
tmp_table_size = 32M
wait_timeout=500
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
[mysqld_safe]
socket = /var/run/mysqld/mysqld.sock
nice = -5
open_files_limit = 8192
[isamchk]
key_buffer = 8M
sort_buffer = 8M
read_buffer = 4M
write_buffer = 4M
!includedir /etc/mysql/conf.d/

Configuring nginx

References:
- nginx wordpress config
http://wiki.nginx.org/Wordpress
- Nginx + PHP-FPM + MySql + APC + WordPress
http://shortbutuseful.com/88/install-nginx-phpfpm-mysql-apc-wordpress-debian-6/
- Optimizing WordPress with Nginx, Varnish, APC, W3 Total Cache, and Amazon S3
http://danielmiessler.com/blog/optimizing-wordpress-with-nginx-varnish-w3-total-cache-amazon-s3-and-memcached

Each line represents a separate command to be executed in sequence!

mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.org
mcedit /etc/nginx/nginx.conf

–insert:

user www-data;
worker_processes 1;
pid /var/run/nginx.pid;
events {
use epoll;
worker_connections 512;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
error_log /var/log/nginx/error.log;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 3;
server_tokens off;
access_log off;
client_max_body_size 32m;
client_body_timeout 60;
client_header_timeout 60;
send_timeout 60;
reset_timedout_connection on;

# If using Cloudflare, uncomment the following to get proper originating IPs
#set_real_ip_from   204.93.240.0/24;
#set_real_ip_from   204.93.177.0/24;
#set_real_ip_from   199.27.128.0/21;
#set_real_ip_from 173.245.48.0/20;
#set_real_ip_from 103.22.200.0/22;
#set_real_ip_from 141.101.64.0/18;
#real_ip_header   CF-Connecting-IP;
# end Cloudflare

gzip on;
gzip_disable "MSIE [1-6].(?!.*SV1)";
gzip_vary on;
gzip_static on;
gzip_proxied any;
gzip_comp_level 9;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

Each line represents a separate command to be executed in sequence!

mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.org
mcedit /etc/nginx/sites-available/default

–insert:

upstream php { server 127.0.0.1:9000; }
server {
listen 8080; ## listen for ipv4; this line is default and implied
#listen [::]:80 default ipv6only=on; ## listen for ipv6
root /home/[USER]/www;
index index.php index.html index.htm;
server_name [HOSTNAME];
location / {
root /home/[USER]/www/;
index index index.php;
try_files $uri/ $uri /index.php?q=$uri&amp&$args;
port_in_redirect off;
}
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
access_log off;
log_not_found off;
expires max;
root /home/[USER]/www/;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
fastcgi_pass php;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/[USER]/www/$fastcgi_script_name;
include fastcgi_params;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_intercept_errors on;
fastcgi_ignore_client_abort off;
fastcgi_connect_timeout 60;
fastcgi_send_timeout 360;
fastcgi_read_timeout 360;
fastcgi_buffer_size 128k;
fastcgi_buffers 8 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
location ~ /.htaccess { deny all; log_not_found off; access_log off; }
location ~ /.htpasswd { deny all; log_not_found off; access_log off; }
location = /favicon.ico { allow all; log_not_found off; access_log off; }
location = /robots.txt { allow all; log_not_found off; access_log off; }
}

Fix CGI Path Info

mcedit /etc/php5/fpm/php.ini

–find:

cgi.fix_pathinfo

Uncomment the command by removing the ; in front and replace the defauly 1 with a 0!

Configuring PHP5-FPM

Each line represents a separate command to be executed in sequence!

mv /etc/php5/fpm/php-fpm.conf /etc/php5/fpm/php-fpm.conf.org
mcedit /etc/php5/fpm/php-fpm.conf

–insert:

[global]
pid = /var/run/php5-fpm.pid
error_log = /var/log/php5-fpm.log
log_level = notice
emergency_restart_threshold = 5
emergency_restart_interval = 2
process_control_timeout = 2
daemonize = yes
include=/etc/php5/fpm/pool.d/*.conf

Each line represents a separate command to be executed in sequence!

mv /etc/php5/fpm/pool.d/www.conf /etc/php5/fpm/pool.d/www.conf.org
mcedit /etc/php5/fpm/pool.d/www.conf

–insert:

[www]
;prefix = /path/to/pools/$pool
listen = 127.0.0.1:9000
listen.backlog = -1
listen.allowed_clients = 127.0.0.1
listen.owner = [USER]
listen.group = [USER]
listen.mode = 0666
user = [USER]
group = [USER]
pm = dynamic
pm.max_children = 15
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 10
pm.max_requests = 0
pm.status_path = /fpmstatus
ping.path = /ping
ping.response = pong
request_terminate_timeout = 10
request_slowlog_timeout = 10
slowlog = /var/log/$pool.log.slow
;rlimit_files = 1024
;rlimit_core = 0
;chroot =
;chdir = /
catch_workers_output = yes
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f [email protected]
php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 32M
php_admin_value[date.timezone] = Europe/London
php_value[upload_max_filesize] = 10M
php_value[max_execution_time] = 120

Configuring Varnish

Each line represents a separate command to be executed in sequence!

mv /etc/default/varnish /etc/varnish/default_old
mcedit /etc/default/varnish

–insert:

START=yes
NFILES=131072
MEMLOCK=82000
DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,1G"

Each line represents a separate command to be executed in sequence!

mv /etc/varnish/default.vcl /etc/varnish/default.vcl.org
mcedit /etc/varnish/default.vcl

–insert:

backend default { .host = "localhost"; .port = "8080"; }
acl purge { "localhost"; }
sub vcl_recv { if (req.request == "PURGE") { if (!client.ip ~ purge) { error 405 "Not allowed."; } return(lookup); }
if (req.url ~ "^/$") { unset req.http.cookie; } }
sub vcl_hit { if (req.request == "PURGE") { set obj.ttl = 0s; error 200 "Purged."; } }
sub vcl_miss { if (req.request == "PURGE") { error 404 "Not in cache."; }
if (!(req.url ~ "wp-(login|admin)")) { unset req.http.cookie; }
if (req.url ~ "^/[^?]+.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.|)$") {
unset req.http.cookie;
set req.url = regsub(req.url, "\?.$", "");
}
if (req.url ~ "^/$") { unset req.http.cookie; } }
sub vcl_fetch { if (req.url ~ "^/$") { unset beresp.http.set-cookie; }
if (!(req.url ~ "wp-(login|admin)")) { unset beresp.http.set-cookie; }}

Configuring vsftpd (optional)

I’m using vsftpd to provide a secure means of accessing the server which is bound to the system user, locked to their home directory and can only be accessed using TLS encryption. Access is also provided via SCP (SSH) of course but most people use sFTP still and there are a good few apps for iOS (etc) devices that only support (s)FTP rather than SSH/SCP. Feel free to omit this step if you don’t need FTP!

Ref: http://ubuntuforums.org/showthread.php?t=518293

Each line represents a separate command to be executed in sequence!

mv /etc/vsftpd.conf /etc/vsftpd.conf.org
mcedit /etc/vsftpd.conf

–insert:

listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
idle_session_timeout=600
data_connection_timeout=120
nopriv_user=ftp
#ascii_upload_enable=YES
#ascii_download_enable=YES
chroot_local_user=YES
chroot_list_enable=NO
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/private/vsftpd.pem
userlist_deny=NO
userlist_enable=YES
userlist_file=/etc/vsftpd.allowed_users
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
force_dot_files=YES
max_per_ip=2
max_clients=20
pasv_min_port=12000
pasv_max_port=12100
require_ssl_reuse=NO

 

echo [USER] >> /etc/vsftpd.allowed_users

Enabling SSL

Ref: http://www.cyberciti.biz/tips/configure-vsfptd-secure-connections-via-ssl-tls.html

/usr/bin/openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem

Configure your SSL as you please. Eg. Country code ‘GB’, location ‘London’, name [yourhostname]

Installing WordPress

Each line represents a separate command to be executed in sequence!

Become the user, go into the web root in its home directory we created earlier. Then download, unpack and move wordpress files into place. Lastly we remove the wordpress directory.

su [USER]
cd /home/[USER]/www
wget http://wordpress.org/latest.tar.gz
tar -zxvf latest.tar.gz
mv wordpress/* /home/[USER]/www/
rmdir wordpress

Creating a database for WordPress

Each line represents a separate command to be executed in sequence!

mysql -uroot -p
CREATE DATABASE wordpress;
GRANT ALL PRIVILEGES ON wordpress.* TO admin@localhost IDENTIFIED BY '[YOUR_PASSWORD]' WITH GRANT OPTION;
quit

Securing your VPS

I’m using Iptables as my firewall here. Note that blocking port 9000 (our PHP FPM) you will get Bad Gateway errors! There’s probably room for improvement here but for now adding the port to the allowed rules fixes this.

// Show what is loaded in our firewall

iptables -L

// Flush everything we have in our firewall

iptables -F

// Allow established sessions

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

or

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

// Allow services

iptables -A INPUT -p tcp --dport 7742 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
iptables -A INPUT -p tcp --dport 9000 -j ACCEPT
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -p tcp --dport 12000:12100 -j ACCEPT

// End iptables by blocking everything that we didn’t explicitly allowed earlier

iptables -A INPUT -j DROP

// backup iptables to a file

iptables-save > /home/[USER]/iptables.rules

// to restore our rules

iptables-restore > /home/[USER]/iptables.rules

Making sure iptables rules are reloaded on reboot
Ref: http://www.debian-administration.org/articles/445

mcedit /etc/network/if-up.d/iptables

–insert:

#!/bin/sh
iptables-restore < /home/[USER]/iptables.rules

 

chmod +x /etc/network/if-up.d/iptables

Reboot to make sure it is working (iptables -L)

Starting and stopping our services

Since I’m a lazy sysadmin I like to use scripts to help me do as little as possible. Here are two very simple scripts, not even very good ones, but one starts all services and the other stops them.

The Stop Script

mcedit stopscript.sh

–insert:

#!/bin/bash
service mysql stop
service memcached stop
service varnish stop
service nginx stop
service cron stop
service postfix stop
service vsftpd stop
/etc/init.d/php5-fpm stop

The Start Script

mcedit startscript.sh

–insert:

#!/bin/bash
service mysql start
service memcached start
service varnish start
service nginx start
service cron start
service postfix start
service vsftpd start
/etc/init.d/php5-fpm start

Note that Varnish prefers to be started before nginx for some reason, although the ports are different.

Chmodding +x the scripts will make them executable, which is handy for scripts ;o

chmod +x startscript.sh stopscript.sh

Run the scripts and have a look

sudo ./stopscript.sh

Sudo is important as we need superuser powers to mess with services! If all goes well you should see output from the commands in the terminal. Check to see stuff really is not running by issuing the following:

ps aux

Once satisfied all is off you may like to find out how little (or much) memory you are using:

free -m

Great, let’s start everything and do this again:

sudo ./startscript.sh
ps aux
free -m

Again you should have seen services starting, ps aux will show you what’s running and free -m will let you know how much memory is being used.

Problems

To see what’s running on which port:

netstat -tulpn

For some weird reason I have to stop nginx, then start varnish and then start nginx again as varnish will otherwise refuse to bind to port 80 despite nginx running on 8080! This is taken into account in my start/stop scripts above.

Closing Notes

Exim Installation and Configuration on Debian

May I point you in the general direction of an excellent how-to guide written by Phil Paradis over Linode?

Link: http://library.linode.com/email/exim/send-only-mta-debian-5-lenny
http://library.linode.com/email/exim/send-only-mta-debian-6-squeeze

You may have to do this:

apt-get install exim4-base exim4-config

then

apt-get install exim4-daemon-light

and lastly

dpkg-reconfigure exim4-config

Thanks to Dleonard0 (http://ubuntuforums.org/showpost.php?p=10411454&postcount=4)

To test your set-up you probably need something like the mail command or in fact mailx:

apt-get install bsd-mailx

This will enable you to do this:

echo "This is a test." | mail -s Testing [your email address]

Check what’s happening with:

mailq

Free Memory

Without nginx, php-fpm, mysql, memcached, varnish, vsftpd, cron, and postfix running the vps consumes ~14MB. Running are bash, ssh, iptables, and atd. Please note this is with a single active user session.

Using a different virtualisation technique these results may differ.

Also, using a more lightweight ssh server (like dropbear) will also save you some RAM.

I have 128MB in total, of which 14MB are used with just the bear neccesities running. This is our baseline.

With all services, but vsftpd running and one user accessing the wordpress powered website, the memory usage figures are somewhat higher.

Throwing vsftpd into the mix we end up roughly the same figure, give or take an MB or two.

Script to show memory usage

I just recently came across a very handy script written by Draig Brady at pixelbeat.org, that shows memory usage per program in Linux. You can find it on his website. Note that this script shows usage per program, not per process.

wget http://www.pixelbeat.org/scripts/ps_mem.py
chmod +x ps_mem.py
sudo ./ps_mem.py

The APT problem

This looks OK but sadly APT and Aptitude are consuming a lot of memory doing their stuff when updating and installing software. Especially Aptitude is eating a lot. (ref: http://blog.aplikacja.info/2009/12/aptitude-vs-apt-get-memory-usage-on-debian/)

There appears to be no way to tweak this other than installing packages manually. However, I rather bump up my VPS memory to 256 or 512MB than having to maintain things by hand the old fashioned (and more efficient way). Call me lazy but time is money ;D

Conclusions

In closing, yes you can run this all quite nicely on a small low end box but expect to work on it a lot harder, whether it’s tweaking settings or maintaining software, it’s great fun. If you really must have the smallest VPS and ignore APT then install from source and sort out dependencies manually.

However, if you are running a business like me, then spending a wee bit more a month on a slightly larger VPS and perhaps selecting a host that doesn’t have ‘rock bottom’ pricing but offers a little more help, makes a a more sensible choice.

Shameless self promotion

If you like, I have this VPS ready made for you to move in to and even configure it to suit your details (username, hostname, passwords). The latter which I suggest you change upon first login of course. A 128MB openVZ container as described here with 3GB space (extendible within reason free of charge!) can be yours for a token amount of just £9.99 including VAT (£8.32 exclusive).

Drop me an email stating ‘WordPress VPS’ in the subject line and the link to this post to get one today!

Small Print

Payment is via Paypal (monthly subscription) and you will get a proper VAT invoice from my UK LTD company. Support is via email, Skype, IM (various) or the old fashioned way by phone during business hours and via email at all other times. I promise to respond to your enquiries within the hour during business hours.

The price includes the (extortionate) charges PayPal levvies but it’s the simplest way to get things done.

There are no bandwidth restrictions as such and I encourage you to make use of Cloudflare’s excellent and free (as in beer) service to help reduce wastage. Your VPS shares a metred 100Mbit connection. The server is based in France and is hosted by OVH. It has 16GB of RAM and 120GB of SSD space in total which is shared amongst everyone. Most VPSs are my web design customers and I like to keep an eye out to make sure everybody receives the best service possible.

For other restrictions please see OVH’s terms as they will block the whole server if one customer is found in violation of them. Hence why I make sure this doesn’t happen by reserving the right to refuse service to anyone who I find might not play by the rules.

Related posts in this (little) series:

What are you doing for a living? How are you using this little tutorial? Let me know and leave me your comments below or drop me a tweet.

If you like this page, please share it

  • Pingback: Testing Nginx with APC, Varnish, Wordpress and W3 Cache on a 128MB VPS | Axel Segebrecht's Blog

  • Adam Howard

    I spent a long time trying to find away to put Varnish with Nginx. For a linux noob, it’s not an easy task and even harder when you take into account that there is so many Apache guides and nothing comes pre-configured with nginx.  So this was helpful and believe it or not, I applied it to my vBulletin site.  Speed is nice, but small problem and I can’t imagine this not affecting WordPress either…. Can’t log-in or can’t stay logged in.  Cookies don’t seem to like passing through between Varnish and Nginx.  

    • http://www.axelsegebrecht.com/ Axel Segebrecht

      Hi Adam, glad to be of service :)

      Cookies are in fact a major problem when using Varnish and will tweaking on both its own settings and the CMS/forum used. I am not familiar with vB from a hosting perspective but I’d read up on the Varnish and Cookie situation in general here:

      https://www.varnish-cache.org/trac/wiki/VCLExampleCacheCookies 

  • Anonymous

    hi,

    thanks for very nice tuts. really useful to me.

    btw, what possible cause if i got 503 error?

    • Anonymous

      when i try to stop n start the service, i got these errors.

      Starting nginx: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)nginx: [emerg] still could not bind()nginx.

      • Paul

        I’m having the same problem as od3n.  Any thoughts?

        • http://www.axelsegebrecht.com/ Axel Segebrecht

           I had a similar problem and solved it by starting varnish before nginx. Are you using the start/stop script?

          Have a look again at: http://blog.axelsegebrecht.com/how-to/install-nginx-apc-varnish-wordpress-and-w3-cache-128mb-vps/#Starting_and_stopping_our_services

          “For some weird reason I have to stop nginx, then start varnish and
          then start nginx again as varnish will otherwise refuse to bind to port
          80 despite nginx running on 8080! This is taken into account in my
          start/stop scripts above.”

          • Paul

            Yeah, I tried that.  I did eventually get NGINX to start, but I was running into a problem where :8080 was appended to my URLs.  I realistically don’t need Varnish right now, so I gave up and just focused on optimizing a WordPress caching plugin.  I’ll probably revisit Varnish in a couple weeks once I’m more familiar with NGINX.

          • Paul

            thanks for the write-up by the way, it’s fantastic!

          • Thompson

            Paul. I had the same issue. What was happening was that I had Nginx server blocks in which I had not explicitly defined “listen 8080;”. If you have even one server block that doesn’t explicitly define what port is being listened on, then Nginx will default that server block to listen on 80, so when Nginx restarts, it finds a conflict since Varnish is already on 80. So just make sure to explicitly define “listen 8080;” within all server blocks.

  • http://dzhotov.com/ dzhorov

    Thank you so much for this post. I’ve been searching around the net for a decent guide on how to properly setup Varnish and I found your blog. The issue I’ve been having was that users could not login anywhere due to cookie conflict with Varnish. Your Varnish config did the trick!

  • Sumesh

    I’m getting an nginx 502 bad gateway error after install.
    Googled and saw a bunch of fixes, but I don’t know which one I should try. Any pointers?

    • Thomas H

      Sumesh, make sure the PHPFM is running. I am guessing you did not replace [USER] in your config files ;)

  • Pingback: NGINX + WordPress | Paul Ruescher

  • Pats

    how do u create a proper hosting with this?
    - create user
    - create users chowned web folder
    - create users ftp account
    - script to create emailids

    Is there any scripts handling these steps?

  • Mahirudin Alkhoir

    i am having problem when add more than one vhost in nginx, error like this
    “Starting nginx: nginx: [emerg] duplicate upstream “php” in /etc/nginx/sites-enabled/www.mysite.org.conf”

    what’s missing configuration?

  • Pingback: Blitz.io Tests Against Apache Worker, Apache Prefork, Apache with PHP-FPM, and Nginx with PHP-FPM in a 256MB RAM VPS - VirtuallyHyper

  • http://www.midbeam.com/ Rohit Agarwal

    Nice detail for lowend vps user…. Very helpful post for me!!

  • Pingback: Guide: WordPress with Maximum Performance and Speed

  • Rob Corry

    Great tutorial helped me out alot, my sites are running alot faster than my previous apache install and i havent bothered with w3 cache plugin yet, can you tell me whats the best way to implement the domain mapping with this configuration ?