§ The 5-minute LAMP Stack

With the release of Debian 7.0 "Wheezy", PHP 5.4 is available though apt-get from the word go. This means it now only takes a few minutes to setup a lightweight web server capable of dealing with the latest web applications with very little configuration. I use the term LAMP loosely in this article because it's easier to pronounce than LNMP.

My usual requirements for a web server are as follows:

These are now all available in the Wheezy repositories, so all we need are a few commands.

Firstly, for a fresh build you'll want to get the basics right:

apt-get install vim htop ntp nscd

echo "your.fullyqualified.hostname" > /etc/hostname
hostname -F /etc/hostname

dpkg-reconfigure tzdata

Grab the LAMP packages:

apt-get install nginx php5-cli php5-fpm php5-mysqlnd php5-xcache php5-curl mysql-server mysql-client

This is always good practice for your MySQL server:

mysql_secure_installation

Setup SMTP, see Linode's simple guide for step-by-step instructions on the second command here:

apt-get install exim4-daemon-light mailutils
dpkg-reconfigure exim4-config

Now let's lockdown the server a bit, you may like to use this gist as a base for your firewall rules - be sure to read through them though or you'll lock yourself out:

apt-get install iptables-persistent fail2ban

vim /etc/iptables/rules.v4 # Add your rules to this file
service iptables-persistent restart

Time to wire PHP-FPM and NGINX together:

# Disable fix_pathinfo
sed -i "s/^;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/" /etc/php5/fpm/php.ini

# Tell FPM to use TCP
sed -i "s/^listen = \/var\/run\/php5-fpm.sock/listen = 127.0.0.1:9000/" /etc/php5/fpm/pool.d/www.conf
sed -i "s/^;listen.allowed_clients/listen.allowed_clients/" /etc/php5/fpm/pool.d/www.conf

service php5-fpm restart

mkdir /etc/nginx/global

Create the file /etc/nginx/global/fpm.conf and use the following for it's contents:

location ~*\.php$ {
    try_files                $uri =404;

    fastcgi_split_path_info  ^(.+\.php)(/.+)$;
    include                  fastcgi_params;
    fastcgi_index            index.php;
    fastcgi_param            SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_intercept_errors on;
    fastcgi_pass             127.0.0.1:9000;
}

Nearly there, create your server block in /etc/nginx/sites-available/your-domain.com:

server {
    listen 80;
    server_name  your-domain.com;
    root         /var/www/your-domain.com;
    index        index.php;
    include      /etc/nginx/global/fpm.conf;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}

Finally, symlink your configuration file and reload NGINX:

ln -s /etc/nginx/sites-available/your-domain.com /etc/nginx/sites-enabled/your-domain.com
service nginx reload

That's it! As long as your DNS is pointing in the right place you should be good to go.

The setup above has been designed to give decent performance for PHP web applications. The htop binary gives a much nicer view of resource usage, whilst ntp keeps your clock in sync and nscd will cache DNS queries made by your web applications.

The PHP Fast-CGI Process Manager allows the web server to delegate run-time compilation of your PHP scripts to a separate process, unlike mod_php5 for Apache. The MySQL Native Driver for PHP is the recommended option above mysqli and is part of the PHP core. Xcache will give you opcode caching, you could also use APC or Zend Opcache.

Hopefully all of the above will result in decreased server load, latency and maximise throughput on your server by making the most of the available resources.

§ Building a Xen Hypervisor

Wikipedia states that a hypervisor or virtual machine manager (VMM) is a piece of software, firmware or hardware that creates and runs virtual machines.

I started off by reading about which operating systems were best suited to what I would've called the Xen host. I now know the correct terminology to be "Domain 0" or dom0 – as hypervisor terminology dictates that each machine is a domain (including the host). It seems you can run Xen on a variety of Linux distributions but I noticed quite a bit of documentation and articles focusing on Debian. For this reason I picked Debian Squeeze.

The primary hard drive on my target system is 120 GiB, this doesn't leave much room for the VMs. Luckily the Xen wiki recommends LVM which is trivial to setup using the Debian OS installer during dom0 creation. With the LVM partition in place on the drive I can easily grow and shrink partitions as requirements for each virtual machine changes over time. This allows me to make the most of what little space I have available on the drive.

Initial installation and configuration of Xen with Xen Tools can be done by following the guide on the Debian wiki.

One concern that struck me was that VMs would be able to access my home LAN as everything is connected to the same router. To solve this issue I setup four LAN subnets and 802.1q VLAN tagging in order to create network segregation. The following steps are not required to setup Xen, they just happen to suite my particular network setup and requirements.

Setup the VLANs on your router and make note of the tag IDs (10, 20, 30 and 40 in my case).

Enable the 802.1q kernel module and make it permanent:

modprobe 8021q && echo '8021q' >> /etc/modules

Once you've done that you'll need to install the vlan package:

apt-get install vlan

Setup the /etc/network/interfaces with as many of the above VLANs as you require for the dom0 and domUs, here's mine (shortened for display):

# The local loopback interface
auto lo
iface lo inet loopback

# Instruct all interfaces to startup automatically
auto eth0
auto eth0.20 xenbr20

# The only physical interface (Ethernet Port 0)
iface eth0 inet dhcp

# VLAN ID: 20
iface eth0.20 inet manual
    vlan_raw_device eth0

# The Xen Bridge allowing VMs to access VLAN 20
iface xenbr20 inet static
    address 10.0.2.2
    netmask 255.255.255.0
    gateway 10.0.2.1
    bridge_ports eth0.20
    bridge_stp on
    bridge_maxwait 10

In order to give the VMs within the VLANs internet access you'll need to enable IPv4 forwarding and NAT on dom0:

echo 1 > /proc/sys/net/ipv4/ip_forward
echo 'net.ipv4.ip_forward=1' > /etc/sysctl.conf
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Ensuring that iptables retains these rules on boot:

apt-get install iptables-persistent
iptables-save > /etc/iptables/rules

With all of this setup you can begin creating VMs. Here's an example using xen-tools to create a VM with hostname 'newvm':

xen-create-image --hostname=newvm \ # Each domU should have a different hostname
    --memory=256mb \
    --vcpus=1 \
    --lvm=vg0 \                     # Specify Logical Volume Group within LVM
    --dhcp \                        # Allow DHCP
    --pygrub \
    --dist=squeeze \                # Setting the distribution to Debian Squeeze
    --passwd                        # Prompt for root password during creation

Here's a quick bash script that makes it easy to delete VMs:

#!/bin/bash
[ -z $1 ] && { echo "Specify hostname!"; exit 1; }

xm destroy $1
xm delete $1
xen-delete-image --lvm vg0 $1       # You may wish to change the LVM group here

Incidently, LVM has an excellent snapshot feature which I've wrapped up into this gist.

§ A Website in a Single HTTP Request

This website has no assets. There are no CSS files, no external JavaScript sources files, no backend scripting engine and no database storage system. It's just one HTML file and that's it. I've decided to get back to basics with my personal site; maybe because I spend my working life optimising complex systems, it's a sort joyful escape.

There's something about plain text that's always appealed to me. Besides character encoding there's not much really to worry about. I know what I'm typing now will display correctly on your laptop/phone/tablet, regardless of your browser – because there isn't really anything to go wrong. I guess it's like my first car in a way, forget about the electric windows, heated windscreen and all those other fancy gadgets and you still have a car.

I must admit that resisting the temptation to use CSS3 transitions or pure JavaScript to spice up the interactivity layer is somewhat difficult. It does however provide a nice clean scope for the design. Either I can achieve it with raw HTML and a couple of lines of CSS or I'm simply not going to implement it here. I want to focus on the content of this site, I want to share what I'm learning as it's happening. Designing the next-best has been on my to-do list for too long.

All content on this site is free to share, just like the web should be.