Webhosting woes, part 1

I've recently been doing some webhosting setup and I thought I'd detail some of the experience and knowledge gained here. In part to make sure I don't forget myself, in part because a lot of the solutions to the problems I encountered I found online, on blogs and what not.

The situation

The premise for the whole thing is that I've got a dedicated server and I want to utilize it for hosting various sites and services. I want to do this in a way that allows me to isolate individual sites/services so that if one site fails/is hacked/explodes then it won't take everything down with it. The best solution for this, as far as I know, is running virtual containers - every site and service runs in isolation, using a bit of the overall resources.


The first task, the focus of this post, is getting OpenVZ running. I had at first been experimenting with LXC - the successor to OpenVZ for newer versions of Ubuntu - but I was stuck in the mud with nothing working using that (I'll likely post my experiences with that at some other point). So instead my money was on OpenVZ running on Debian Lenny - which turned out to be a fairly good choice as installing it was a breeze. Here's how I made it work:

Step 1: getting the kernel in shape

OpenVZ needs a slightly modified kernel to be able to do some of its magic, so the first step is to install a modified kernel.

sudo apt-get install linux-image-openvz-686

If that goes as it should (i.e. no errors) you then need to reboot the machine. When it comes back up again, check that the kernel is  now in fact the proper one.

uname -r            #should show something with openvz
ps -eF | grep vz    # should show [vzmond]
ifconfig -a         # should show a venet0 device

Step 2: change kernel parameters through sysctl

On the host machine, you then need to allow packet forwarding for ipv4 addresses. The reason behind this is that you'll normally want network connectivity for your containers - allowing them to be accessible to each other and the host. Modify your /etc/sysctl.conf to look like this:

net.ipv4.conf.default.proxy_arp = 0
net.ipv4.conf.all.rp_filter = 1
kernel.sysrq = 1
net.ipv4.conf.default.send_redirects = 1
net.ipv4.conf.all.send_redirects = 0

As well as enabling ipv4 forwarding, you're disabling ARP, enabling filtering of IPs (a sanity of IP addresses), enabling SysRq, ignoring icmp echo broadcasts, and setting some basic settings for network interface redirects (not necessarily the best, it seems - see this forum post on the matter).

After modifying the sysctl.conf file, update the kernel runtime parameters with the values by executing this:

sudo sysctl -p    # update kernel runtime params with values from /etc/sysctl.conf

Step 3: have fun!

The host system is basically ready now to get containers up and running. All you need to do is create or download some container templates. Seeing as a lot of people have already been through that one, you can easily get your hands on templates through the OpenVZ template downloads. Store container templates in /var/lib/vz/template/cache - and remember not to unpack them after downloading.

Before creating containers, it's worth setting some defaults for container creation. Edit /etc/vz/vz.conf to set preferred template (from the ones you downloaded or created), if any, and proper iptables params. The latter is important if you feel like creating more fancy iptables rules inside containers. I personally modify my vz.conf to:

IPTABLES="ip_tables ipt_REJECT ipt_tos ipt_limit ipt_multiport iptable_filter
    iptable_mangle ipt_TCPMSS ipt_tcpmss ipt_ttl ipt_length ip_conntrack
    ip_conntrack_ftp ip_conntrack_irc ipt_LOG ipt_conntrack ipt_helper
    ipt_state iptable_nat ip_nat_ftp ip_nat_irc ipt_TOS"

Then, to create a container, issue the following commands:

sudo vzctl create <id> --ostemplate <osname>       # <id> is an ID *you* choose for the container
                                                   # <osname> is the name of the container template, less the .tar.gz
sudo vzctl set <id> --ipadd <ip> --save            # <ip> is the internal ip you want to assign the container
sudo vzctl set <id> --nameserver <ns_ip> --save    # <ns_ip> is the ip of a nameserver to use
sudo vzctl set <id> --hostname <hostname> --save   # <hostname> is the hostname to use for your container

If these commands run without errors, you should be able to start the container with:

sudo vzctl start <id>

You can check that the container is running by issuing:

sudo vzlist

And you can step into the container by issuing:

sudo vzctl enter <id>

And that's pretty much the basics of it. There are obviously a lot more one can do, like securing the entire install with proper firewall rules, etc - but that's for another time.