Glossary Of Terms:
Production site: The live website where all your web visitors go.
Test site: A copy of your live site, at a different URL, where you can make experimental changes without affecting your live site
Drupal and its modules are in pretty constant development. So things are changing pretty fast and sometimes not completely documented. In practice, that means making a change or adding/removing a module on your prod site can have rather surprising results - surprises you'd rather your visitors didn't have to live with. That's why I recommend making all changes to a test site, and if they work out, promote the changes to your prod site.
Here's how I built a completely parallel site on my hosted, shared server account.
First I need to mention some things about my site, so the rest of this article makes sense:
- My site is called example.com
- it's hosted on a shared server
- I have shell access to my hosted files. Without shell I wouldn't really want to attempt all this.
- I am allowed to have two mysql databases on my account
- all site files are at
(there's also an alias,
/home/user/www, which points to public_html)
- in the above,
userstands for my username, which I'm not telling you
- I keep my production drupal database in mysql; that db is named
- Apache is set up so that http://www.example.com and http://example.com will point to
All of this is pretty standard stuff, but you may have to make a few changes to this process if your site is set up differently. My test/prod workflow looks generally like this:
- Make a new (empty) database, and name it mydb_test
- Copy your prod db into mydb_test
- Copy all of your prod files (from public_html) into your test directory
- Make three settings changes to connect the test site to the test db
- Make changes to your test site.
- (optional) replicate test site's files and db back into the prod site to make your changes live
So how to actually do all this? Don't worry, it's not that hard once you have the right commands handy. Really, I do steps 1-4 in about 2 minutes. This document is long only because I wanted to be verbose enough for all skill levels!
Step 0 - work with your host provider
The first thing I did was ask my hosting provider to create a new directory,
/home/user/test and then set up apache and their DNS servers so that http://test.example.com and http://www.test.example.com would point to this new
test directory. It was important to ask them to make a new VirtualHost entry in the apache configurations, NOT just set up a rewrite rule. They should know what you mean by this - and they might charge you extra for it. Mine didn't, but even if this costs you a couple of extra bucks, it's worth it. Trust me when I say that using a rewrite rule or subdirectory of your existing site will make the rest of this much harder to do.
When this is complete your directory structure will look something like:
|(empty because we haven't put anything here yet)
/home/username could in your case be /var/www/username, or something else entirely. The point is to have a test directory which is not part of your normal html directory, and which acts as a separate site in all ways.
You'll also need a second mySQL database to house your test site's data.
Step 1 - Create an Empty Database
I use the commands
mysql -uuser -ppassword -e "create database mydb_test;"
mysql -uuser -ppassword -e "grant all privileges on mydb_test.* to user@localhost identified by 'password';"
to create my database and set the permissions. The I broke a single mysql command into the last two lines because drupal.org wasn't printing it all as a single line. If you are restricted from doing so, you may need to create the empty database via cPanel, Plesk, or whatever control panel your provider gives.
Step 2 - Replicate the database
mysqldump -uuser -ppassword --add-drop-table mydb_prod > ~/temp/prod-db
mysql -uuser -ppassword mydb_test < ~/temp/prod-db
Above you see the commands I enter. You'll need to change things user and password to your username and password; also mydb_prod should be replaced with the mySQL database name for your prod site. Knowing that, I bet you've already figured out that you need to replace mydb_test with the name of your newly-created test database.
The first line just creates a directory to hold our temporary dump file.
The second line, starting with
mysqldump, is where we dump the entire prod database to a textfile. We use the --add-drop-table option because this essentially creates a script we'll run later; this option makes sure that script will erase old data before importing new data. Note that you need to supply the proper username and password for your production database. I specify the database name mydb_prod - you will need to change this to the name of your prod site's database. The textfile created by this command is actually a full script which will create tables and populate them with data.
The third line, starting with
mysql, is where we do that. Again, be sure and replace the italicized parts with the username, password, and database name you set up in step 1.
Finally I delete the dump file (
~/temp/prod-db); it's not needed anymore now that we have loaded it into mySQL.
Step 3 - Copy the web files
rm -rf ~/test
cp -R ~/public_html/. ~/test
Here I remove the test directory, then recreate it, and copy everything from ~/public_html into it. I remove the test directory and all contents because I may copy of the test site in there, and I don't want it to pollute my fresh new exact replica of my prod site.
Step 4 - Edit Settings
This starts the nano editor (or use whatever you like) and loads drupal's settings file. Here you will need to change two lines:
$db_url = 'mysql://user:password@localhost/mydb_test';
$base_url = 'http://test.example.com';
These lines are not together in the file. Set the database connection line, pointing to the test database you created in step one and populated in step 2. (in other words, you need to replace the words user, password, and mydb_test with information that's correct for your test database.) The base_url line sets the URL you will point your browser at to use the site. Save the changes.
Note: If you have previously upgraded your site from Drupal 6 to Drupal 7, the manner in which the database connection is specified in Drupal 7 has changed. What is more, the drupal 7 installer appends the new method at the end of settings.php rather than where it originally was following the instructions. The best remedy is to copy the content of default.settings.php (which has all the drupal 7 documentation) as settings.php and modify that accordingly. It's a good idea to do this on your production site, too.
Now, in your web browser, navigate to the site - it should be working fine. But I also change the Name field at administer --> settings to TEST.example.com (all caps) so its easy for me to remember I am looking at the test site.
Step 5 - Make your changes
This is where you make you changes. Change settings, add/remove modules, muck with the code - it's up to you. Remember you are working in a copy of your site - one that users don't know about - so you don't have to worry that you are creating problems for the users.
Killes has written a very nice and very quick way of testing your site at node/11521
And if you don't like the changes, or if you mess up your test site
completely - no worries! Just re-do steps 2-4 to bring a new copy of your
production site and database into your test environment.
Step 6 - Promoting changes to production
Now that you have your test site the way you want it, you really have two choices.
Method 1: You can re-make all the same changes manually on your production site.
Method 2: You can basically migrate the test site into production, with a very brief outage for the users.
I usually use method 2, but have been known to do it both ways. To use method 2, I'm essentially doing everything mentioned above, but this time copying the test site into the production location. So I'll skip over it more quickly this time around:
mysqldump -uuser -ppassword --add-drop-table mydb_test > ~/temp/test-db
mysql -uuser -ppassword mydb_prod < ~/temp/test-db
rm -rf ~/temp/test-db
rm -rf ~/public_html/*
cp -R ~/test/. ~/public_html
nano ~/public_html/sites/default/settings.php(here you'll edit the db_url and base_url to the prod-site settings)
- Also be sure to open the prod site, navigate to administer // settings and change the name back to the way it should be for the prod site.
You should probably test your site again using the Killes method linked in step 5.
There are a couple of additional cleanup steps I do, once I know my site is in good shape:
rm -rf ~/test/*(just cleaning out test dir for next time)
rm ~/bash_history(because it has my database password in it)