Setting up a dev -> prod system in Drupal

Here I'll discuss the setup of a pair of Drupal websites, one a development ('dev') site and one a production ('prod'), and a system allowing the migration of state between them (promotion).  This discussion, and the procedures described assume the presence of my Drupal Script Library.

Motivation

In many cases, especially those of high-visibility, high-importance sites, it is desirable to see how changes will affect a site before releasing the change to the public.  A new module, new content, or even updates need to be tested in a development environment before being effected on the production site.

Having a development environment on which changes can be staged allows assurance that a change doesn't have any negative effects as well as giving stake-holders an opportunity to sign off on the change before it goes live.

One way to do this is to make the change on a copy, and, after ensuring that it had the desired effect, make the change again on the live copy.  Obviously, this is prone to errors.  The process set out here offers an automated way of site state promotion between dev and prod.

Initial prod site setup

The first step is to set up the production site.  This is a normal Drupal site deployment.  If the site already exists, skip this step -- there is no need to do anything special to the initial version of the production site.

Creation/setup of dev site

Now, it's time to create the development site as a copy of the production site.

Initial creation of dev site from prod site state

After the initial production site has been created, we need to use that site's state as the initial state for the development site.  We can use the drupalSiteCopy.sh script to duplicate the prod site onto the dev site.  Configure your webserver for the new development domain name (e.g. 'dev.<production domain>') and ensure a database is available for the new development site.

drupalSiteCopy.sh -nomunge <prod site domain> <dev site domain> <dev db name> <dev db username> <dev db password>

We specify the -nomunge flag as we don't want to change references to the production domain in the database.  After this runs, follow the instructions the script generates.  At this point, the development site should be a duplicate of the production site.

Setting up simple auth for dev site

Normally, we want to control access to the development site so pre-release versions of the site can not be seen to the public (even if the development domain is not publicly known). 

The easiest way to do this is with HTTP basic authentication -- it's easy to set up and doesn't require the modification of anything w/in the Drupal site (unless you have no access to the webserver configuration).  This discussion assumes the apache.org httpd. 

See: http://httpd.apache.org/docs/2.2/howto/auth.html

As described there, you need to create a password file someplace outside the Drupal installation.  The file needs to be readable by the web server process.  There's really only need to create one username/password -- remember, this is to control access to the site only, let Drupal control fine-grained permissions.

htpasswd -bc <filename> <username> <password>

Now, to enable the basic auth against this file, you can either edit the apache configuration or the dev site's .htaccess file.  Updating the apache configuration is easier as we won't have to have differences in the prod and dev sites' .htaccess files.  I'm only going to discuss the former.  If you don't have access to the apache configuration, you'll add the relevant changes to the .htaccess file in the root of the Drupal site and revert that file to the CVS version upon site promotion.

Add the following to your apache config:

<Directory "/FULL/PATH/TO/DEV/SITE/DEPLOYMENT">
        AuthName "dev site"
        AuthType Basic
        AuthUserFile <fully qualified filename of password file created above>
        Require valid-user
</Directory>

After that, reload your apache config and you should be all set.  You can now reference your dev site at
http://<username>:<password>@<dev site domain>/

Another possible mechanism of protecting the development site would be to remove the "access content" permission from the 'anonymous user' role and programmatically add it back upon site promotion.  This could be tied with the LoginToboggan module so bringing up any page will prompt for login.  This is left as an exercise for the reader -- feel free to send me  a comment on this.

Dev -> prod promotion

At this point, we have two identical sites.  The workflow would be to make changes to the development site, do whatever is necessary to ensure the changes worked/are acceptable/etc, then promote those changes (site state) from development to production.  This last step is described here.

Performing content checks

Before performing the actual site promotion, we want to perform some checks  on the development site's content to ensure that there are no references to the development site.  We need to check for URLs that refer directly to the dev site (i.e. contain the development domain name) and for URLs that contain the development site's domain in the path (rather than the production site alias symlink).  If any occurrences are found, they need to be fixed before promotion.

drupalDBQuery.sh findsitename <dev site domain>

This query is fairly crude in its operation -- basically a simple grep across node content looking for the development site domain.  If any references to the develompent domain name are found, they need to be either fixed or at least verified that their presence is specifically desired.

Migrating site state

At this point we should be fairly certain that the content is ok to migrate the site's state from dev to prod.  This is as easy running the drupalSiteCopy.sh script to copy dev onto prod.  Remember that any site aliases for the target site must be removed before doing the copy and restored afterwards.

Here's an example script:  (Note that this script is just a starting point.)

#!/bin/bash

# This script will sync the development site to the production site.

DEV_SITE='<dev site domain>'
PROD_SITE='<prod site domain>'

# confirm
echo " "
echo "This will sync the development site to the production site completely clobbering the current production site."
echo "Press <return> to continue or ^C to quit..."
read

# Ensure there are no mentions of the dev site in the server.
if [ -n "`drupalDBQuery.sh -quiet findsitename $DEV_SITE`" ]; then
    echo "Found references to dev domain in development site's database:"
    drupalDBQuery.sh findsitename $DEV_SITE

    echo "Press <return> to continue if this is acceptable, or ^C to quit..."
    read
fi

# remove any existing aliases for prod here...
aliases="drupalReport.sh aliases $PROD_SITE"
for alias in ${aliases}; do
    drupalAlias.sh -remove $alias
done

# perform sync
drupalSiteCopy.sh -noconfirm -nomunge $DEV_SITE $PROD_SITE

# recreate aliases for prod
for alias in ${aliases}; do
    drupalAlias.sh $alias $PROD_SITE
done

When running the script, it's important to follow all the directions generated by the drupalSiteCopy.sh script to reset the file permissions of the prod site (as root).  (Note that this not necessary on all hosts).

hope this helps....

Free Tag:

Comments

Hi,

Great article,

Will this also replace nodes table in production site?

 

I'm not exactly sure what you're asking; but I think the answer is 'yes'.  When you copy a "dev" site overlaying the "prod" site, everything is overwritten -- including the 'nodes' table.