In previous articles I have discussed how difficult it is for users of a shared web hosting service such as Webfusion’s to develop and to debug applications on a service that they’re using to provide services such as a blog or a forum to a client community over the web. In my view, there are two main challenges to developing on such ‘production’ environments:
- The supplier of the hosting service will typically optimise the service for normal access – that is for live use – and this usually involves disabling all debug features and diagnostics.
- The development process can temporarily ‘break’ functional code or introduce bugs. You will normally want to keep the existing service running in parallel to this development without its failing.
For these reasons, mature IT organisations invariably separate out development from live ‘production’ and use multiple environments for development teams, pre-production testing, user trials, production itself and support. Not doing this is asking for trouble and is just bad practice, so I use VMs hosted either on my laptop or on my home Ubuntu server to do all such testing. I find that a standard Ubuntu LAMP stack (such as on my laptop) is good enough for functional development. However this type of LAMP stack is different in subtle but important ways from the Webfusion shared service architecture, so I have also set up a VM configuration which far more closely mirrors the Webfusion set-up.
Just in case others would like to do this, I have used this article to explain how I did this in some detail. Unfortunately it has grown quite large as I’ve documented this. I apologise for its length. To keep the article manageable, I have split it into the following sections: deciding on your requirements, choosing the VM for you and building and configuring the VM. I will also be deferring some content to a later article.
Deciding on your requirements
I would recommend at a minimum for any developer for a web application:
- Don’t make untested changes to production. Use a development/test environment which is quite separate from the production (and use more if if is necessary to work on multiple aspects which you want to keep separate). Make sure that each such environment appropriately mirrors the live environment. (I’ll discuss this later.)
- Use some form of development cycle base around this / these environments:
- For each change decide what its scope is and how it needs to be tested.
- Develop and test the change on the development environment.
- When you are confident that the change is working successfully then release the change into production, making sure that you have some form of simple rollback strategy if things go wrong.
Of course you might be able to buy extra environments from your service suppliers, but in my view this is a waste of money and not as effective as having a local environment over you have administrative control. I will be discussing how to use a free VM product to configure a VM to use as a test service for the LAMP-based Webfusion shared services, but I first want to discuss a few issues.
- What is an ‘appropriate’ development environment? At a minimum, you will need to have somewhere to run a LAMP stack. I use Ubuntu for all of my home environments, so my main laptop already supports a LAMP stack, and this is adequate for most purposes. I have a copy of my blog engine here that I use to author articles before “syncing” them to the public service. However if you are running Windows then running Apache/PHP/MySQL over Windows (WAMP) is a pain to set up and is also different to LAMP in many ways, so IMHO, it’s just a lot easier to run a LAMP VM. A typical default LAMP stack is not the same as that configured by Webfusion, and these difference can sometimes be significant. It is a lot easier to tailor a dedicated LAMP VM to mirror the target production environment as I do in this article.
- Release and Rollback. By ‘release‘, I mean the process of moving a tested set of changes onto your production service. There are many ways to do this, but unless your application is absolutely huge, the simplest method is probably the best. What I have a _private/kits directory, and I copy any releases into this in the form of a .tar.bz2 file. (I could just as easily use a zip file, but using a single compressed file makes the copy a lot easier under FTP or a WebDAV-based explorer.) I also have a simple script for each application that takes the ‘release ID’ as a parameter and explodes the corresponding kit into the target application directory hierarchy. Rollback is easy: release the previous version using the same script. I use a remote command (as I discuss in this article) to execute this script, but you just as easily create a PHP variant which you invoke over the web and which takes the application, release ID, and enabling password and run as a child process. Remember to ensure that the release script does not overwrite any content subdirectories, if the application hierarchy includes these (e.g. using an --exclude option or equivalent in the script).
- Consider using Source Version Control. I use Git in my development cycle, so I typically just keep the current and previous versions on my production server, as I can remake any historic version easily. However, setting up this sort of system can be quite complex, so you might just prefer to keep a local archive of your release kits.
Choosing the VM for you
The first thing that you need to decide is which virtualisation product to use. There are two clear alternatives in my opinion:
- VMare Player. This is the simplest end-user VMware product to use within a desktop / laptop environment, and the one that I initially used at home because it’s the market leader and I’d used VMware at work. I would avoid the free VMware products as they are either obsolescent or too complex for this type of simple VM application. One advantage of using VMware is its Appliance Store which provides simple pre-build LAMP appliances such as the free TurnKey LAMP Appliance which I discuss below.
- VirtualBox (commonly abbreviated to VBox). This is the main market alternative to VMware, and in my view is the easiest product to install and to use on Windows, OS X and most major Linux variants. Unlike VMware Player, VBox includes a fully featured VM development environment. The disadvantage for starters is the lack of an integrated appliance store, but many of the store subscribers offer ISO downloads such as Turnkey’s.
I switched to using VBox about five years ago, and I would still recommend it overall because of its features, performance and wide platform support, so the remainder of this article assumes that you will be using VBox as your virtualisation platform.
The next step that you need to do its to understand your vendors hosting environment:
- Which versions of Apache / PHP / MySQL are you running. The starting point here is the response from a phpinfo() request (as I’ve discussed in my earlier Webfusion articles) that tells me what I am running, but I also ended up running httpd -v, php -v and mysql --version on the server to get the versions (Apache/2.2.3, PHP 5.2.16 and MySQL 5.1.52)
- Which PHP and Apache modules are loaded and how they are configured. I exported a tarball of /etc/httpd and /etc/php* to work this out as PHP runs as a cli child image of mod_suphp rather than an in-process library within mod_php.
- You need to replicate this closely on your VM and be aware of any material differences (e.g. some nice PHP features such as anonymous functions were only released with PHP 5.3 and don’t work under 5.2). However, the main issue here is to cover the feature that you use, e.g. you might decide not to bother with some modules that you don’t use in your applications.
Building and Configuring the VM
- Step 1: Install the VM product
See VirtualBox Downloads. In the case of Windows and OS X this is an self-installing exe / package which you download and run. In the case of Linux variants the Linux page tells you how to add the Virtual box repository to the sources so that you just use your standard package installer to do the initial install and track any product updates. For this type of VM, VirtualBox is pretty much load and go.
- Step 2: Initial install of the VM product
I have used TurnKey’s LAMP Appliance over VBox in this example. You will need to tailor this script if you use another media (such as the Ubuntu-supplied 10.04-LTS CD distribution or the Ubuntu 10.04 LTS netboot mini.iso) or use VMware Player as your VM product. The sweet-spot for this appliance is Amazon EC2, but it is still a good starting point for me to use here. The advantages of this appliance is that it is packaged minimal Ubuntu 10.04-LTS LAMP server build (~ 210Mb download compared to 680Mb for the standard Ubuntu ISO), and has some nice management tools preinstalled that novice sysadmins will find useful. There are two possible approaches to using it: the first is to download the OVF version of the appliance, unzip it and use the VBox import function to convert / import into Virtualbox. However, I find it easier just to use the ISO version and do a bare load.
Use the VirtualBox->New Menu option to create a new VM:
- Linux/Ubuntu VM;
- System: 384 Mb;
- Boot:CD+HDD, no floppy;
- Storage: the IDE Controller is sufficient, so add a new 2Gb HDD to the IDE primary master (this will leave about 1Gb for your Application + database, so increase this if you need more), add the LAMP distribution ISO to the secondary master; delete the SATA controller;
- Network: enable a single adapter bridged;
- Audio and USB: disabled;
- Everything else is as per the defaults.
Now start the machine and hit enter to boot into the Linux installation. Select “Guided – Use entire disk” as the partitioning method and hit enter. Let the installer split the disk (into the root and swap partitions), select “Yes” and hit enter to continue. Select “Yes” to the question “Install the GRUB boot loader to the master boot record?” The system will now install the LAMP stack, prompt to remove the CD (which you do by hitting right-clt then selecting the Devices->CD->host drive then hitting enter; the sytem will now boot into Ubuntu. This all takes a couple of minutes.
The Turnkey configuration menu first prompts for root and MySQL root passwords. This is a test VM which will only be accessible locally from your PC, so I suggest using a common password for all these as there’s little point in high security (but don’t do this for live systems). Skip the Turnkey Backup and Migration feature, and skip daily security updates. You will now be presented with the URIs for web access, WebShell, Webmin, PHPMyAdmin, and SSH/SFTP. Now select Advanced->Shutdown to close down the server. When you restart, you now have all of the features that you need to tailor your server to your specific development needs.
Two hints here: (i) you don’t need to shut down the VM when you’ve finished using it; you can instead simply save it to disk by using the Hostkey(Right-Ctl)-Q option in the VBox console window. (ii) You don’t need to have a VBox console window running (and keep capturing you mouse if you accidentaly select it) as you can do everything that you need to do with the WebShell, Webmin, PHPMyAdmin, and SSH/SFTP tools provided; instead use the VBoxHeadless -s {vmname} -v off from the command line to start your VM and VBoxManage controlvm {vmname} savestate to save it.
- Step 3: Tailor the VM to mirror your production service
At this point you have a good platform to do most of your LAMP development. However in my case the VM is different to the Webfusion service (WfS) in some ways that I accept. However I want to mirror some of these, so I still need to have more work to do:
- Apache: (WfS:2.2.3 vs VM:2.2.14). Accept as there are no material function changes between these versions. WfS loads a richer set of authorisation modules but I don’t use this functionality. It also uses mod_suphp and mod_expires as opposed to the VM which currently supports mpd_cgi and mod_php, and these have different runtime characteristics so I want to fix up these.
- MySQL: (WfS: 5.1.52 vs. VM:5.1.41). Accept as there are no material function changes between these versions.
- PHP: (WfS: 5.2.16 vs.VM:5.3.2). Accept as there’s little that I can do about it as obtaining a 5.2 version is a pretty stretch. The main issue here is that I need to avoid using the new PHP 5.3 functionality.
So what this really boils down to is that I’ve got to swap out mod_php for suPHP (this also requires dropping the PHP Xcache accelerator as this isn’t supported under suPHP and isn’t used on WfS anyway. I also want to add some extra components to make debugging easier and facilitate transfer from VM to the hosting machine and the production VM. My goal is to have the VM look identical to my Webfusion environment at a PHP programming level. I am more relaxed about other differences between the VM and the production service that are visible at a PHP coding level so I have decided not to mirror these (for example the VM only runs one user service and uses an in-VM database and file storage, whereas Webfusion runs thousands of users on a server farm with the dedicated database dedicated servers and the user file storage on Network-attached storage (NAS). The listings below gives the command scripts that I used to tailor the system.
I will discuss copied the /etc updates (for Apache, suPHP, &c) in a following article. You can just paste this into a WebShell window on your server to do this yourself. (You will, of course, need to change this if you are using a service other than Webfusion shared LAMP service.) I am currently only using this to test PHP scripts so I need to think about what I do about python support etc..
- Step 3: Install the application on the VM
You need to set up entries in your hosts file to map test versions of your domain onto the VMs IP. I allocate all my VMs static IPs in the address range 198.162.1.128-250, and so this is easy, eg.
192.168.1.245 ellisons.org.home blog.ellisons.org.home files.ellisons.org.home ...
You can now use an SFTP, SSH, WebShell, etc. to access and set up the VM in very much the same way with the target service.
Listings — VM tailor script
The first step is to install some additional tools that I find useful for debugging:
apt-get update apt-get install linux-image-virtual \ libapache2-mod-suphp php5-cli php5-gd php5-imagick php5-curl \ php5-xdebug vim zip unzip bzip2 strace halt
After restarting the VM booting the the virtual kernel (This will now be the default and is labelled linux-image-generic-pae for some reason), I strip out the Turnkey components that are really aimed at is Amazon EC2 offering:
apt-get remove linux-image-generic php5-xcache libapache2-mod-php5 lvm2 \ tklbam tklbam-duplicity tklbam-python-boto webmin-tklbam apt-get clean apt-get autoclean apt-get autoremove rm /var/cache/debconf/*old /var/cache/apt/*cache.bin rm /etc/php5/conf.d/{imagick,xcache}.ini rm -R /etc/tklbam /usr/lib/tklbam rm /etc/cron.daily/tklbam-backup DISABLE_MODS="authz_default authz_groupfile cgi perl python reqtimeout ssl" ENABLE_MODS="auth_digest authn_anon authz_dbm expires headers include rewrite unique_id" for m in $DISABLE_MODS; do rm /etc/apache2/mods-enabled/$m.*; done for m in $ENABLE_MODS; do ln -s ../mods-available/$m.load /etc/apache2/mods-enabled/$m.load; done
Lastly I set up a shadow account so that my working UID / directory is in the same location as on the Webfusion system. Here I just execute this script with parameters /websites/LinuxPackage02/el/li/so ellisons.org.uk 9999999 terrye "Terry Ellison" :
NAMEROOT="$1" DOMAIN="$2" USERID="$3" USERNAME="$4" USERDESC="$5" DOCROOT=$NAMEROOT/$DOMAIN addgroup --gid $USERID $USERNAME mkdir -p $DOCROOT/logfiles chgrp $USERNAME $DOCROOT/logfiles chmod 750 $DOCROOT/logfiles adduser --uid $USERID --ingroup $USERNAME --home $DOCROOT/public_html --gecos "$USERDESC" $USERNAME
To be be covered in next article: Apache config changes, Mysql account set up, …