Beginners guide to setting up a staging environment/ site on Linux, Apache, CentOS with password protection

So I need to setup a staging environment. I’m doing it on CentOS using the command line. This means I have a SSH connection to my server and have sudo privileges. But before that let’s begin by settings up a DNS entry in a control panel – if you don’t have that then you need to contact your web host.

This is what we want to create: a subdomain called “thestage” which will make the URL for access “”. 300 is the TTL(time to live) and I’m not sure whether it’s right. Since it’s inaccessible to the public I’m going to experiment with that value for a little while.

thestage 300 IN CNAME

If it’s not an IP address then you need a full stop at the end.

I created a directory on this server for the staging contents. This will make it a top level directory like /var /etc /usr etc. It felt appropriate.

mkdir /thestage

I setup a vhosts (virtual hosts) conf file. This essentially means we can relay different addresses through the httpd (HTTP daemon) like Apache to different folders. This is how a lot of web hosting is conducted. So if you have access to vhosts then you can do this, if you don’t you’re probably on a hosting package that limits your ability to do things like this. Talk to your hosting provider and probably don’t continue reading the rest of this until you can do the aforementioned.

Because my httpd.conf (httpd configuration file) includes all ‘.conf’ (configuration) files in a directory of vhosts configuration files I can make a single instance specific/ bespoke version by creating a new virtual host configuration file (see below). If I didn’t/ couldn’t do this I would have to include it in the httpd.conf file which is possible but  can get messy if you have a lot of information and a lot of virtual hosts. The httpd.conf file is probably somewhere like /etc/httpd/conf/httpd.conf. (if you can’t find it do this: “cd /” … “locate httpd.conf”. Instead I put one here /etc/httpd/vhosts.d/thestage.conf where “thestage.conf” is the name of the file and vhosts.d is a directory being included because of the following line in httpd.conf:

Include vhosts.d/*.conf

I put this inside it to just test everything works first off:

<VirtualHost *:80>
    DocumentRoot /thestage

    # Other directives here


Since we’ve made a change to httpd we need to restart it

If your user has it setup – not guaranteed (sorry, look elsewhere for that) – then use this:

service httpd restart

Otherwise (or if it doesn’t work) use the file path too:

/etc/init.d/httpd restart

now go to and you should see the default Apache page.

So go to /thestage and create index.html (this is the command line way, you could just use a program like WinSCP to create it and edit it in a GUI).

touch index.html

Then open that file to add contents

sudo vi index.html

(assuming you can and do use sudo, not discussed here)

Press [i] to enter “insert” module

Write anything, e.g.

Hello, world!

Press [Esc] to enter command mode

Type (they’re capitals btw):


and press enter, this saves and quits

Refresh your browser and you should then see:

Hello, world!

So since that works we can get on with password protecting Since it’s a staging site it’s essentially still testing and we don’t want the world seeing it!

So the password advice in this Apache link didn’t work when I first tried it presumably because the path or something wasn’t set for me to use it so I had to do use the following command: locate htpasswd

# locate htpasswd

The one I wanted is /usr/bin/htpasswd

So being in the directory with the program:

cd /usr/bin

we will almost be ready to use the command from the Apache link above. I have decided to not use /etc/.htpasswd so I will make a new file in my directory


If you want to put it somewhere else which doesn’t yet exist then you will need to use mkdir with the -p argument to make the parent directories. For example:

# mkdir -p /usr/local/apache/passwd

But, still being in the /usr/bin directory with the htpasswd program (enter the command “pwd” if you’re not sure if you’re in that dir) type the following to create the new .htpasswd file and add a password to be used with yourusername (your user name) as below. If you’ve already got a .htpasswd file as in /etc/.htpasswd then you don’t need the -c argument.

htpasswd -c /usr/local/apache/passwd/.htpasswd yourusername 

Then you’ll need to enter and re-enter your password. This should work, if it doesn’t you might want to try another directory.

Then you’ll need to change the file ownership:

chown apache:apache /usr/local/apache/passwd/.htpasswd

Then create a .htaccess file in your your directory /thestage and add the following lines:

AuthType Basic
AuthUserFile /etc/httpd/.htpasswd
AuthName "Enter password"
Require valid-user

Or wherever your file is in place of “/etc/httpd/.htpasswd” Save it and restart apache (httpd) again as before.

Refresh your browser and now you should have a login form.


et voilà!

Now, depending on your needs you have the ability to setup a new database (a staging version of your live one) and a new codebase (perhaps with Git, I’ll come to that later, if I go down that road…)

Thanks :)



Recommended resources:–net-29738


Drupalgeddon :(

Man, choose the worst week to go on holiday why don’t you?!

So this has happened and it’s a pain in the bum and there’s not even any sure fire why of knowing whether or not your site/server has been compromised. Even after updating the problem is that as is described in this post on Drupal Stackexchange patching or updating Drupal core does not mean you have rid yourself of the problem. So I’ve updated to Drupal 7.32 and run Drupalgeddon but now there’s every chance that the best thing to do is rebuild the server. Man, what a pain in the arse!

Good clear guide to get started on understanding Drupal’s AJAX form functionality

This is a good article posted by Randy Fay on the form API changes from AHAH to AJAX forms in Drupal. For some reason I find the AJAX form functionality of Drupal incredibly confusing. This might be because I’ve never really had a chance to get my fingers into AJAX in any capacity, let alone for Drupal. So the underlying concepts I know, loosely and on a high level, but I’ve not had a chance to practise. So if you’re really struggling, maybe you should ditch Drupal at this point and get some AJAX stuff working.


General error: 1005 Can’t create table Drupal error when creating foreign keys

I kept getting “General error: 1005 Can’t create table …” when trying to add foreign key integrity constraints to Drupal through MySQL and db_query(). I had the schema defined through hook_schema() and I was putting the db_query() which had the foreign key constraint definitions in hook_install(), I tried them in hook_update_N() too which is all by the book and correct (either way is legit).

It turns out my school boy error was that the types did not match…

Unavoidably helpful modules and resources for Drupal module developers

Form Builder module

  • install all the modules that come with Form Builder Example
  • then for a GUI visit:
  • build the form and export the code then add it to a form building function as in drupal_get_form(…)

Schema module

  • install
  • then visit:
  • or just click “configure” on the row with the schema module on the module listing page
  • click ‘inspect’
  • from there you can export a database table that you can make the traditional way in SQL or through PHPMyAdmin or similar
  • with that export you can

Web development testing process, methodology and checklist resources

This is a collection of resources on testing procedures, processes, methodologies, checklists or just related. In my experience, when you’re out of university one of the first things that ends up being dropped is the rigour of testing. Deadlines won’t wait and unlike when you’re studying, there’s no way you want to be up until two o’clock in the morning drinking energy drinks. Let me tell you now that dropping testing is a mistake.

Keep your testing procedures in place, keep your logging process in place. Take the time to keep your Gantt chart up-to-date and all the way along keep the methodology documented and tidy. If you do not do these things you will kick yourself later. Like sick leave or christmas parties it’s simply something that must be an overhead in business that you take into account. This is the job.

Resources: (please note some of these are rather old-skool development house style and therefore slower and heavier to assimilate, should you bother to read them at all)

Also, another for the pile – setup a staging server


Adding an update to a Drupal custom module during development


This is a post on how to write an update for a custom module that you have been developing on Drupal 7. To do this there are some prerequisites. Firstly – you must have used a ‘.install’ file (MY_MODULE.install) in your custom development (and you must have added that MY_MODULE.install file to the list of files in your file). You must have then installed your module by way of the typical /admin/modules route. If you’ve not done that then you need to – you’ll reap the rewards later as Views, Entities and a whole heap of other functionality will open up to you but you must use the code that declares your schema to Drupal, inside your MY_MODULE.install file.

Updating the existing schema definition

The first step in the update process proper is to add your new definition to the hook_schema() function

 * Implements hook_schema().
function MY_MODULE_schema() {


Hook update: the hook_update_N() function

Now you will need to add that same definition to the hook_update_N() function, but the manner in which you add it is different.

Firstly write the function declaration. This will be your module name replacing the word ‘hook’ and then your update identifier replacing the capital N. This to be honest still confuses me – I think the documentation on it is extremely confusing. So when the first number didn’t work (7001) I just used 7002 instead.

function MY_MODULE_update_7002(&$sandbox) {
    $schema['your_new_table'] = array(
        'description' => 'this is your new database table created through hook_update_N',
        'fields' => array(
            'id' => array(
                'description' => 'the ID of your_new_table',
                'type' => 'serial',
                'unsigned' => TRUE,
                'not null' => TRUE,
            'text' => array(
                'description' => 'some kind of text as an example',
                'type' => 'varchar',
                'length' => '128',
                'not null' => TRUE,
    db_create_table('your_new_table', $schema['your_new_table']);

Don’t forget to clear your cache (using drush, “cd” into the Drupal folder then type “drush cache-clear”, or …/admin/config/development/performance)

If that still hasn’t worked you might need to increment your update number.

Finally, making it happen on your system

So now all we need to do is backup our database and then visit /update.php and follow the instructions!

Recommended resource: this is a really good guide to the process (scroll down to the appropriate step that you’re on)

Recommended resources

Database functions to use in your update:!database!

hook_update_N() information: Community Documentation on Writing .install files (Drupal 7.x):

The connection was reset error message in web browser like Firefox when there has been a change to Drupal usually in moving sites around

This is the page you want to look at:

To be specific, this post:

I had a similar problem that I could NOT figure out for a few hours. My Google search brought me here more than once but none of the comments above helped me figure out what was going on. I finally stumbled upon this other post:

FINALLY a fix that worked for me. I decided to add the link to this post just in case someone else is trying to find a solution to the same problem I was having. (hopefully this isn’t off topic!)”



Just downloading Microsoft’s SkyDrive, I mean OneDrive

Before I had a chance to get used to the SkyDrive, it’s now been re-branded as the OneDrive. How often do Microsoft plan to change major brands? It’s disconcerting to see this, it feels like an admission of a lack of control. I like Microsoft, I have absolutely no problems with them. The near-monopoly they held on the personal computing industry feels like nothing compared to the near-monopoly Google has on the internet, and Facebook has on social networking (or rather, our personal lives as they’d like us to believe). I say that because I feel I have to turn to Microsoft as the provider of both an acceptable price and an acceptable privacy policy. All of that said, I have no idea of either the price or the privacy policy of Microsoft in this mobile era of computing. Microsoft have just completed their Nokia purchase however so I may be speaking too soon (not that this has been a slow process!)

Article in on measuring user behavior with metrics like clicks etc.

I’m asked a lot about metrics for measuring traffic, engagement etc. etc. Even though on a daily basis I have to deal with complex developing, people management, daily requests and tasks I still find grasping truth behind the behaviour of our end-users/ readers a slippery kipper…

So I must make some time to finish reading the following article from on what we think we know about measurement, click-throughs, clicks etc. compared to pausing, engagement and how it all fits together with social sharing.

Time article “What You Think You Know About the Web Is Wrong”

Using Pathauto functions in a block to create lists of Taxonomy terms and their associated nodes/ content with a custom content type where one node could have multiple terms

The problem

I came across a need to write a custom block in Drupal 7 which dealt with Taxonomy terms in a custom Taxonomy vocabulary. In this block I needed to list all nodes that were associated with that Taxonomy term, the problem was that one node could have multiple terms associated with it in the Views field. I started out using Views for this but found no way to prevent the Taxonomy terms from being listed multiple times per node so I decided to reverse the approach and list the terms in the Taxonomy which had the specific vocabulary.

For the full explanation of the problem see this post on Drupal Answers.

In working on this I went in circles for about an hour creating invalid URL aliases to match the clean URL pathauto alias that I had generated when the content was first created. However what I needed was to obviously match the path that was created in the first place. I realised that the way that I was going to do this was by returning back to the Pathauto module and checking through that api.

The solution

This is how I ended up getting it to work:

$vocabularyID = $row->taxonomy_term_data_vid;
      $termID = $row->tid;

        $path = drupal_get_path('module', 'example_sites');
        include_once($path . '/example_sites.api.php');
        $nidArray = fetch_node_ids_by_term_id($termID);
        $path = drupal_get_path('module', 'pathauto');
        include_once($path . '/');

        foreach ($nidArray as $nid) {
            $node = node_load($nid);
            $string = $node->title;
            $cleanTitle = pathauto_cleanstring($string);
            $url = 'category/' . $cleanTitle;
            //below is just applying a class for CSS styling etc.
            $options['attributes'] = array(
                'class' => 'category-with-term',
            $link = l($node->title, $url, $options);
            print $link;

Please be aware that fetch_node_ids_by_term_id($termID), here:

        $path = drupal_get_path('module', 'example_sites');
        include_once($path . '/example_sites.api.php');
        $nidArray = fetch_node_ids_by_term_id($termID);

…is actually just me consulting the database, you can replace all that with this…

    $nidArray = db_select('taxonomy_index', 'ti')
        ->fields('ti', array('nid'))
        ->condition('tid', $tid, '=')

Learning How to Theme in Drupal – Finding the Right Beginner Guide to Theming for Developers Who Already Have Experience in Drupal

When it comes time to learn something new in Drupal, the best thing that I can recommend for you to do is to search for the best place to start. Invest a little bit of time so that you can be fairly sure that the area that you are about to start looking at for your guide is the right place. I’ve wasted a lot of time on books and websites that either have bad information, out of date information or are too focused to be of any help.

When it came to theming, I found that the best thing to do was to watch this video but accept that you might not understand everything it says. Then download a theme, open the theme in e.g. Eclipse, setup with XDebugger, set breakpoints in .tpl.php files and template.php files and debug – watch the process, following the debugging through the files and you’ll understand just how complex it is. At this point you might want to go back over the video.

I then made a mistake and tried to get too deep too fast, by all means mess around with the code, experiment and play around but don’t aim for it to be your final version, that’s a waste of time – don’t try and take shortcuts.

After messing with CSS and even changing the ordering and the contents of a page (possibly even liking what you’ve seen) you then need to get back into structured learning. I would then suggest you read the first few pages of the Drupal documentation on theming and then watch this video which really helps you to see what is being discussed.

A simple and easy practical guide for beginners on setting up your Drupal web development environment with Wamp, virtual hosts, Eclipse IDE and XDebug debugger

Starting out with Drupal or require some help with setting up your web development environment?

Drupal is becoming quite common, I know people who have jobs in development organisations that focus solely on Drupal development for their clients and one person’s job is just to ‘theme’ those Drupal builds. The chances are that Drupal will become more commonplace for web developers as clients look for increased functionality that sometimes lacks in WordPress (Joomla is another that is often spoken of for this purpose but that’s not something I can help you with) but don’t want the overhead of creating a bespoke system from scratch (which also wouldn’t be regularly updated by a large open-source community).

The first thing to say is that you need to be confident in your development setup – if you already have a good knowledge of debugging and a PHP IDE setup then I don’t need to say any more on that and you can skip the next section – if however you aren’t using virtual hosts, you don’t have a secure debugger, you’re using Windows and you aren’t confident with your IDE then the next sections are for you and I advise you to work through them slowly but surely.

Let’s start setting up your development platform

If you’re using XAMPP I recommend removing it and installing WAMP, I ‘grew up’ with XAMPP but WAMP offers so much more for a beginner/ intermediate developer (and beyond) and if you’re not that confident at editing configuration (config/ conf/ ini) files then get rid of that XAMPP and (or just, if you’ve not got anything yet) download that WAMP!

Issue 1

When downloading WAMP be sure you take note of their recommendation on C++ redistributables – i.e. download and install them. Be aware of your Windows type (32 bit or 64 bit – for an explanation and more information on this check out Microsoft’s guide, but come back). This is important and if you don’t know yours then click Start > (My) Computer > System Properties (a tab towards the top) and there in the ‘System’ section you’ll see your  ‘System type’. Make sure you know it because there will be repercussions later if you don’t.

Download WAMP

Next head on over to WampServer’s homepage to get that lovely stuff. Click on ‘Start using WampServer’ (as of March 2013) and you’ll find a variety of options to download. Great – that’s a good thing! Now if you look at the options, you’ll see it’s slightly misleading as all of the options have Apache, Mysql, PHP, XDebug, XDC, PhpMyadmin, SQLBuddy and webGrind. The versions of these might be different, but don’t worry about that – instead pick the first one in the list that corresponds with your system type – either 32 or 64 bit (unless you specifically have to choose a certain version of something, in which case select that with your appropriate system type)

Now take note of WampServer’s notices and download the Visual C++ Redistributable if required. If you’re not sure – download the one that corresponds with your system type (32 or 64 bit) anyway, the installation screen won’t offer an installation offer if you’ve already got it, instead it will say repair, remove or similar – cancel the process and ignore the Program Compatibility Assistant’s prompt that it might not have installed correctly. After you’ve checked the redistributable, choose the first link in the first paragraph on the WampServer download screen (as of March 2013 this is ‘you can download it directly’ – I won’t include a link because that circumvents the selection of 32 bit or 64 bit as I’m running 64 bit and that link will likely be out-of-date soon anyway). You’ll be taken to a Sourceforge page where you can run/save the file – one way or another you’ll want to run it.

Install WAMP

Allow the installation if you’re prompted by a Windows warning and welcome to WampServer’s installation wizard. Click all the usual disclaimers and select additional icons etc. if you want, in other-words keep clicking next. The extraction of the files will take a minute or so on a modern processor.

When that’s done it will ask you for your default web browser, find your Firefox/Chrome etc. folder (Computer > C: > Program Files (86)) and select the .exe or as it says, ‘If you are not sure, just click Open’ to use Internet Explorer. Installation will finish and you’ll have to select the appropriate networks for it to be working on, I’d advise limiting it to Private networks, ‘such as my home or work network’. Allow that access and click next on the SMTP and Email options, because the chances are you’re not running a mail server on your laptop! Finally we can launch WampServer.


Now you should notice a little ‘W’ icon in your system tray (bottom right) that turns from red, to orange then to green. Then, helpfully, it will disappear. We want that icon to appear permanently in your system tray as you’ll be clicking it a lot. Left click the white up arrow to the left of the system tray and click ‘customize’. Find your WAMP icon (listed under ‘Aestan Tray Menu’ on mine) and choose ‘show icon and notifications’. Now you should have a little green ‘W’ in a box in your system tray.

Setup virtual hosts

This might seem an extraneous step, but it’s far better to get this step nailed now before you start wishing you had a separate sandbox-type (i.e. a safe and independent ‘play thing’) for when you want to try something out or when you inevitably have more than one project on the go.

Setting up virtual hosts is simply a process to follow (detailed here) that allows you to have more than one ‘website’ running on one machine, and it’s commonplace for webhosts to allow for such a thing so it’s worth doing.

Issue 2

If you’re not experienced (at all) in Linux type systems (and therefore file management) or you generally only concern yourself with the actual website’s folders, then this is where WampServer really helps – it provides shortcuts to commonly used files that we need to edit for the virtual host setup. However it can be a good excuse to start familiarising yourself with file management systems that are above and beyond the Windows ‘My Documents’ style setup, so you might want to have a go at finding the files yourself in the Windows Explorer system (the folders and files display from C:\ onwards). Another thing to note is that it’s good to have file extensions being displayed – if they aren’t then to do that click Start > Control Panel > Appearance and Personalization > Folder Options > View (which is a tab) and ‘un-tick’ ‘Hide extensions for known file types’.

Windows Hosts file

The next step is to enter the brave new world (if it’s new to you anyway – otherwise please excuse my condescension) of the Hosts file. This is located in


Helpful tip

A quick way to get there is to select…   C:\Windows\System32\drivers\etc   and copy that into the navigation bar at the top of the Windows Explorer and press return. Otherwise, work your way up the file path.

You should see a folder with hosts, lmhosts.sam, networks, protocol, services or some-such variety.  Interestingly you’ll note that there are no extensions being displayed here (except lmhosts.sam) because there are none, but it’s still important to display them. Now we open hosts, but wait for there is another issue to take note of…

Issue 3

It’s important (and will save you headaches) to realise that although we’re in Windows, not Linux, we do still sometimes have to run certain things as administrator (this should be OK if you are logged in as an ‘administrator’ Windows User Account). Editing the hosts file requires this, so before we open hosts, find Notepad and right-click it, rather than left clicking it as we usually do, and select ‘Run as administrator’ (with a shield icon to the left of it). Allow the User Access Control when prompted then go to File, click Open and find the hosts file (again, copy   C:\Windows\System32\drivers\etc   into the navigation bar at the top and it will take you straight there. It’ll look empty, because it’s looking for files with extension ‘.txt’, so next to ‘File name:’ click on the file type button with the down arrow that currently says ‘Text Documents (*.txt)’ and select ‘All Files (*.*)’. Yata! There you’ll see hosts, open it!

Editing the ‘hosts’ file as administrator

As it says at the top (commented out with #s), this file maps IP addresses to host names, which means we can map our localhost (the not-over-the-internet, not even requiring an internet connection, local network that exists just on our machines) to various host names (‘website’ names) that we want to further match with folders on our computer (i.e. ‘localhost’ network location otherwise being known as ‘somesitename.local’ -> C:\somesitenameDevelopmentProject\). The reason this is helpful is because otherwise we would need to be using a folder in WAMP that is C:\wamp\www\somesitenameDevelopmentProject\ which can get irritating and makes setting up a PHP debugger slightly more cumbersome.

We don’t need to do much here but it helps if you understand the concept underlying this process. You should already have an entry

'        localhost'

That’s showing us that we have an IP address of

which is the loop-back interface of our machine, allowing us to be both server and client – exactly what web developers need. This IP address is matched with the hostname


We want to add entries that match with whatever we want to name our address to access it over a web browser, so if we go with ‘sandbox’ and give it the extension ‘.local’ (for our pleasure) we want an entry that looks like this…    sandbox.local

[TO BE CONTINUED] – apologies for the lack of an ending here, but I figured I’d never finish the guide if I didn’t at least post SOME of it!


Eclipse download

Eclipse is a widely used development environment for various languages, the one we’re interested in is PHP so what we need is Eclipse and the PHP Development Tools (PDT) plugin. I was using Eclipse Helios for a long time and really wanted to upgrade to Eclipse Juno, but I’ve had various problems with Juno and PHP configuring, so instead I rolled back a release to Eclipse Indigo.

The Zend package is a good one to use so you don’t need to fetch the PDT elsewhere and is packaged (unsurprisingly) in a way that works ‘out of the box’. So visit the Zend site for the Eclipse & PDT package and download the Eclipse Zend PDT .zip. Once that’s downloaded, extract it to somewhere like C:\…

Issue xx

When unzipping, Windows can seem to place your extracted contents inside another folder, since we’re looking to create


We want to unzip the contents into C:\ so select that as your destination.

Since Eclipse doesn’t ‘install’, if you want to create a shortcut, do so by right-clicking the eclipse-php.exe and following the creating a shortcut procedure.

Eclipse project setup

Now we want to integrate your existing Drupal structure with Eclipse. If you’ve not actually yet installed Drupal – follow this guide but bear in mind that we don’t want to put our Drupal extraction into a htdocs or www type directory – since we’ve setup virtual hosts.


can have problems with associating content types to php syntax colouring in Eclipse Juno, …

used .. instead


install a plugin

i.e. —

How do you know which form is which when writing hooks and custom PHP code in Drupal

Beginning Drupal can be tough, as I’ve previously written. One thing that drastically improves Drupal PHP development is knowing which form is which. Drupal (at least at the seventh version) is heavily based around forms. Pro Drupal 7 Development by John K. VanDyk spends an extremely large amount of time on forms to the detriment of explanations on Panels, Pages, Views and just about everything else that a builder/ developer needs to learn about.

But I digress, use of the following code in a .module file for your module (replace the “My_Module” part with the name of your own module) will show you which form is which by just visiting it. Vital for all those form_alters etc. that come along in development work.

The code

function My_Module_form_alter(&$form, $form_state, $form_id) {

    drupal_set_message("Form ID is : " . $form_id);


Have fun!

Keep it simple, don’t overstretch with your PHP systems design

I’ve recently had an inherited part of a system completely give up the ghost with many areas breaking maximum execution times. When I dug a little deeper it became clear that in one procedural passage of script there was a horrendous mix of stuff going on. It became immediately obvious that reconstructing it would be a month or so’s job. In the end I questioned the staff member who had direct interaction with it and instead of one processing script dealing with five or six logical functions, we could encapsulate the problem, strip off all of the attached complexity and have one water-tight section.