[Written Autumn 2008] It's taken longer than anyone originally imagined, but
Virtual
Private Servers (VPSs) are finally becoming affordable by the average person
i.e. below US$100 a year. I recently bought one as an extension to nedprod, partially
as the main server for the book Freeing Growth
but also to give me full control over my spam processing as my hosting provider
was getting sick & tired of me overloading his shared server. It was a fair cop
- but much of the problem was because I was limited to a normal user shell account.
With full root access I could do a lot more.

A
VPS
is basically a slice of a normal server, so you rent a bit of a full server with
the size of that bit dependent on how much you are willing to pay. You get your
own full OS installation (which is usually Linux for the cheap VPSs) and you can
do anything with them that you like. You can get VPSs up to half
the size of a normal server but they cost more than I earn in a year, so realistically
I'm in the £5 a month category which doesn't buy you much. With a decent amount
of tuning though you would be surprised what you can achieve, and of course you
can easily convert your VPS upwards or downwards according to demand.

1. Find a decent VPS provider

This is very easy: go to
Low End Box and read through the reviews. Overwhelmingly the US based VPSs are
cheapest, then Germany, then the UK - however, remember that you will be spending
most of your time in a SSH session so ping times are important unless you like long
lags between keypresses. You also get a choice between OpenVZ and Zen - OpenVZ can
be better if the sysadmin is competent and doesn't oversell the box, whereas Xen
is less performant but much more predictable.

I went with buying a full year in advance from
cheapvps.co.uk which is
the unmanaged arm of the respectable VAServ VPS hosting company. If you
buy a full year at once, they will double your VPS spec which meant that I got a
UK-based Xen-based 256Mb RAM, 20Gb HD and 300Gb of bandwidth VPS for just £4.75
a month (US$9). It being UK based got me 65ms ping times from Ireland which makes typing much
easier, plus I chose Ubuntu server for its OS. With cheapvps.co.uk you actually
can choose between OS installations any time you like and there is quite a long
list of alternatives including Windows Server 2003.

I personally would recommend with hindsight that you need a minimum
of 256Mb of RAM unless you are willing to run really ancient server software and/or
you don't mind a sluggish web service. As you will see later on, I aim for 128Mb
to be in use at any given time with a maximum of 192Mb in burst
- this leaves 64-128Mb for caching disc access which you really want if you can,
and remember that there will be a spike in memory usage every time a SSL
connection is formed. If you approach your RAM slice then your VPS will start
swapping and things will slow right down. However, if you can only afford 128Mb
of RAM, then my following instructions will at least get you a working server.

[Added Summer 2009: If you need something with 1Gb of RAM or
more, low end fully dedicated servers are finally becoming affordable -
you can get one from €30/month. See
page three of this guide]

By the end of this, you should have a web server capable of running any PHP and
MySQL based CMS, plus the email service will have excellent spam filtering.

2. Free up RAM

For some strange reason most VPSs will preinstall a 64 bit Linux OS. If you
possibly possibly can, switch this to a 32 bit installation as 32 bit binaries
are significantly smaller and use less memory during use. Chances are that your
VPS will have no shortage of bandwidth, CPU nor disk space - its single &
biggest bottleneck will be RAM. Even if you get your server running smoothly
close to its RAM limit, wait till your first DDoS or bot attack and watch those
memory spikes!

You can replace openssh with dropbear to save a few Mb of memory - it does no
harm and it's not like you need the full openssh. Simply apt-get install
dropbear and apt-get remove ssh and then apt-get autoremove to clean up. Also,
disable a lot of the default tty processes which hang around eating up half a
megabyte each - simply rename /etc/event.d/ttyX to something like /etc/ttyX.off.

Don't forget to add universe and hardy-proposed to /etc/apt/sources.lst and
do an upgrade. If you're really short of RAM, replace bash with dash or
even busybox though you may get shell script incompatibilities. I didn't bother with the latter two and ended up with the
following memory free & processes:

3. Replace root

Firstly, create your own user account (preferably with a random bit on the
end: the technical name for this technique is salting)and add it
either to
/etc/sudoers or the admin group. Check that it logs in and that you can sudo as root. Now
disable root login in dropbear by adding the -w switch to /etc/default/dropbear
extra args.

You probably should install ssh keys and disable password logins, but to be
honest I have a long randomised alphanumeric password which is good enough in my
opinion.

4. Install MySQL + Lighttpd + PHP

Apache is fine for big fast servers but it sucks for small ones. You must use
Lighttpd instead which uses threads instead of forks to handle concurrent connections.
You should also disable InnoDB from MySQL BEFORE doing anything
else as that will save 100Mb of RAM. You can find RAM tuning guides all over the
internet, but basically I ran lighty-enable-mod fastcgi and then I edited /etc/lighttpd/conf-enabled/10-fastcgi.conf:

"max-procs" => 1,
"PHP_FCGI_CHILDREN" => "4"

This basically prevents PHP from handling more than four connections at once -
any extra users just have to wait. A PHP child can consume about 10-16Mb of RAM each so you can increase PHP_FCGI_CHILDREN
if needs be, but for most low traffic sites this will be fine. You should never
increase max-procs past two - it wastes memory by having an extra master php
process, on the other hand it adds resiliency should one of the master php
processes die. Chances are though you wouldn't try running a heavy user site on
a VPS anyway.

4. Secure ALL admin parts of the site

You don't want to get hacked, so you will need to be paranoid about security
- particularly when you are installing, configuring and/or
playing around with your website.
PHP based admin tools such as phpmyadmin are very convenient but are deadly if they
get broken into - you don't even want squirrelmail broken in reality.

To ensure full security, put auth digest (not the older auth
plain) password blocks around every sensitive
area of the website - this requires a user name and password to access. You
should also always password protect an entire site if it may be in anyway
vulnerable. Also, force
the use of HTTPS for all the same sensitive regions - you don't want your emails
nor your SQL transactions being readable if you use them to add passwords etc.

It took me a long time to figure out the lighttpd.conf to make these work, so
here's mine for reference:

Among the many things which this config does, it rewrites any accesses to http://vps.nedprod.com
to use https: instead. It also redirects any usage of phpmyadmin in the other virtual
domains (as the ubuntu package overlays itself on all virtual domains) to use the
vps one. And it sticks auth digest blocks round stuff.

After all of that, here's my memory usage on a reasonably loaded server:

So that's about 58Mb used at this stage - MySQL (sans InnoDB), lighttpd plus
four php5-cgi processes eat up 28Mb of RAM.

5. Setup Firewall + Email + Spamassassin

The best thing to do is to follow the excellent guide at
http://flurdy.com/docs/postfix/ which covers setting up Shorewall, Postfix, Courier IMAP and
integrating both into MySQL. You need to skip the Amavisd and ClamAV steps
however because they chew up 170Mb alone and will reduce your poor server to a crawl.
Be careful to use Shorewall to block off public access to anything until you are
absolutely sure it is secure.

Edit /etc/default/spamassassin to make sure you set up spamd to run under the
spamd user rather than as root and limit its children to one seeing as each
child will chew up 50Mb or so. Spamassassin alone eats 30% of my 256Mb VPS -
it's the single largest memory hog by far. Run sa-compile after every sa-update
to help reduce memory usage and improve throughput, and don't forget to enable
loadplugin Mail::SpamAssassin::Plugin::Rule2XSBody in v320.pre to enable the
compiled rules.

You can see the hefty effect of spamassassin - we have roughly
doubled our memory usage to ~120Mb which is as far as we want to go if
we want to keep our 256Mb server running smoothly.

6. Setup Reverse DNS + SPF

Not setting up your reverse DNS will penalise any email you send from your
VPS by spam checkers, so here's how. Firstly, most VPSs don't have DNS
delegated to them so there is no point setting up your own bind or npd server
unless you want a local caching nameserver (not a lot of point seeing as your
VPS provider has a perfectly good equivalent nearby) - therefore, you should ask
your provider to add the rDNS for your IP, or else use a DNS provider which lets
you have access to your host records (e.g. the very reputable though slightly
more expensive namecheap.com).

For SPF you need to add an IN TXT record to your DNS record detailing every
server which could send email for your domain like as follows:

"v=spf1 a mx include:ukfsn.org ~all"

The include: is for when you may send your email from your ISP's smtp
server instead e.g. if you don't set up your SMTP service on your VPS to
send email for you.

7a. Content Management

I have spent the last two months looking for a decent content
management system and I have installed over ten different CMSs
and database driven systems. I was looking mainly for an integrated
forum, wiki, issue tracker and database-driven display plus
automatic generation of search engine friendly data as well as
disability support and any other easy freebies XML enables. This
website, nedprod.com, still runs along a static HTML data system
whereby I edit the content on my computer, munge it through some
Python scripting and upload it via SSH. nedprod's pages do contain
PHP to implement little things like the hit counter and automatic
page compression (this halved my bandwidth requirements instantly)
but all in all, nedprod's architecture would be entirely familiar to
someone in the mid 1990s. I'm happy with this system - it works fine
for me and gives me the kind of absolute control that I like without
being needlessly annoying on a daily basis. However, Google takes
special notice of the main CMSs nowadays and it doesn't understand
nedprod's data format. Besides, it was about time I modernised my
web programming knowledge - I can't live in the 1990s forever!

What follows are only the ones I tried which I thought anything
of - as you'll notice, they all have the reputation for being very
lean and fast (I didn't even consider them unless they had a
reputation for speed). Obviously, I didn't spent a massive amount of
time on each CMS so you can take my opinion at the time of
writing (Autumn 2008) for what it's worth:

Dragonfly CMS v9.2.1
This PHP based CMS was pretty good for what it did - easy to
install, plenty of options, responsive, good for forum support
especially. I'd recommend it if I were running some sort of
mainly-forum & discussion based site.

Trac v0.11.2 (from Ubuntu repositories)This Python based all singing all dancing collaborative
development tool was a pain to get working - lots of command
line work even with the convenient Ubuntu repository install. I
got it working eventually, but it was unresponsive to use and
the half second lag between page loads was annoying - maybe due
to the SQLite3 backend, maybe just cos it's Python. I got rid of
it fairly quickly.

Redmine v0.8 (from its Subversion repository)This Ruby on Rails based "Trac improvement" was
everything that Trac wasn't. It was MUCH more responsive and has
a much cleaner UI. Unfortunately, it was a bitch to install
because Ubuntu's Rails is broken - not Redmine's fault
obviously. Once you hand install an updated Rails using the
rubygems package manager, it ran very well except for the 40Mb
or so of RAM which Rails needs as a minimum. My only problem
with Redmine is that it's a bit simple - fine for simpler
projects, not so fine for more complex ones. As much as Trac
sucked to use, you can see that it's much more flexible.

Bitweaver v2.02This is speed-optimised descendent of TikiWiki. I
thought it wasn't bad, fast enough, problem was that its module
implementations were a bit simplistic for me. It'll no doubt
mature with time.

Joomla v1.5.8I tried this because it's one of the "top two" in
userbase for the free CMSs. I was fairly stunned in how utterly
rigid it is, how lacking in configurability and it's not fast
either - good enough with xcache (a PHP accelerator) running,
but we're not blazing along here. Why the hell everyone thinks
it so great I do not know - I guess if you have absolutely zero
knowledge of web programming you'd love its WYSIWYG interface.
For me, it was way too toy for real world usage.

Drupal
v6.6After Joomla, I thought okay I'll try its nearest
competitor Drupal. And Drupal is a LOT better than Joomla, but
once again I still found it fairly toy. Your page layout is
still pretty much fixed, so you still have this notion of
"posting news" in order to update content. Maybe I didn't figure
out how to change this, but I want the ability to stick any
frame I like containing anything I like wherever I like on each
& every page and have each page template off a master and
sensibly adjust itself accordingly. Drupal doesn't seem up to
this - I know that BBC News runs on Drupal so don't get me
wrong, it's fine for that kind of website. But it's hardly
flexible in its fundamental premise (insofar as I could find).
I'd still recommend Drupal over Joomla though - it's much faster
and much more configurable, though I couldn't get it to not
"feel" different to every other Drupal site out there. You just
somehow know it's a Drupal site from how it's laid out
and behaves.

Obviously I was getting a bit annoyed by this stage - everything
I tried was good in one or two specific areas, but fairly shocking
in everything else and I wanted a good performer in lots of areas at
once: a one size fits all solution. For example, Drupal is
still using a node based layout and page addressing which
makes all the URLs some random node number rather than a URL which
describes the page content. I had thought that CMSs had moved on by
now, though I guess the fact we still need sitemaps.xml would
suggest otherwise.

If you're happy with PHP based sites, then great you'll be very
happy at this stage - your VPS will handle even fairly heavy loads
with ease even without adding a static proxy. Even if you prefer
Ruby on Rails, you have ample memory to spare to run two concurrent
Rails processes and your VPS will scale moderately well though it'll
scale better with multiple logged in users (which are much harder to
cache) on PHP. However, I wasn't happy at this
stage and I began to wonder what else I could do ...