Completion Time: 1 hour
Skill Level: Advanced
Prerequisites: Basic understanding of the WordPress framework and phpMyAdmin, a live server or MAMP/WAMP.
In this tutorial I will walk you through the steps of migrating WordPress from one folder to another on your server. You will learn how to backup your WordPress database, and the proper steps to take in order to relocate WordPress with as little downtime as possible. We’ll also take a look at different methods of further securing and organizing your WordPress installation. Let’s get started.
STEP 1: SET UP YOUR TESTING ENVIRONMENT
For this tutorial I will be assuming that you will be starting from scratch with a fresh WordPress installation. You can head over to the WordPress download page to get the latest version.
TECH TIP: INSTALL WORDPRESS VIA SVN
If you have no experience using the Terminal, or if you’re not sure if your server has a Subversion client installed, skip this step and simply download WordPress as normal. Subversion is an excellent tool for quickly updating software on a server. It is particularly useful for installing WordPress quickly, as well as updating to the latest version with just a few lines from the Terminal.
Open up Terminal and browse to your htdocs folder. Navigate to your htdocs folder and create a new directory.
cd /Applications/MAMP/htdocs
mkdir testBlog
cd testBlog
Now run the following line:
svn co http://core.svn.wordpress.org/tags/3.0.2 .
SVN will do its thing, and before you know it you’ve got WordPress installed in your directory… In four lines from the terminal.
STEP 2: COMPLETE THE INSTALL
Open a browser and navigate to your localhost phpMyAdmin. We need to set up a new database for our WordPress installation to use. I’ll be calling mine testBlog.
(1 image wasn't archived)
Open your web development tool of choice. I’ll be using Coda. Navigate over to your WordPress installation and complete the installation by renaming wp-config-sample.php to wp-config. Open the file up. Lines 19, 22, 25, and 28 need to be defined in order for WordPress to connect to the database. Enter your details. On a default MAMP install the values are user: root, pass: root, host: localhost.
Now we need to generate our secret keys and salts. Head over to https://api.wordpress.org/secret-key/1.1/salt/ to generate them. You’ll end up with something like this:
define('AUTH_KEY', 'Hmx$^SqUaR:;xV_4(-hug;Vh)Xv9g=;Tu`(vcQH5 w# m|Oz5)Kx233%[VH`qc$*');
define('SECURE_AUTH_KEY', 'hl^K{;MKM1{I4v1-sDP>-o$KiFW9n?D8AAoI:ajw>~ZVH:P]yN?kol&n3dP0}.cH');
define('LOGGED_IN_KEY', 'r~F[3%9?jXR [l.TzQT/G}y<+ks.VTuG[j19zdu^+K/-%&9|XO5b8Ur9CQ1o90b;'); define('NONCE_KEY', 'f$ULA|7)p-2g)xS3O~2{-0ItX#!9hF_l*ldU2Q^o,42lMAhy#?RjN[h)px>kl9V9');
define('AUTH_SALT', 'kCTIy7gUVlk zTp>,d-8T29OYYF7>Y]On+l78Q/.HoeeidEA-tUznuWW6c~@tEpL');
define('SECURE_AUTH_SALT', 'TD|N_*Axd-@Y<#MEM6q*C:>Ek@YC[-EUO|k[XLO&(Pd7@f$>bPT@`~Ev_q4R7{D`');
define('LOGGED_IN_SALT', '&S{jmJLLmj9ge?bA-`6)O14i{ X0&sfZe+j.-9;POg(+m38CnP,Lw_7co9V~q3 8');
define('NONCE_SALT', '4rU=LY-X+Iabh2NnNn3bgaG35MTI]qaW!p;abF0Y7>9iyx
Copy these lines from the browser and replace lines 45 – 52 with your generated keys. I like to copy and paste the first half, refresh the browser and copy and paste the last half again. This way you can be sure your keys are unique.
TECH TIP: WP_DEBUG
You might notice on line 81, you can set WP_DEBUG to true or false. False by default, wp_debug will help to pinpoint errors while developing. If you do use this feature, make sure you set it to false for production.
(2 images from this post weren't archived)
Navigate to your install in the browser. You will need to fill out a few more details to finish the installation. If you are on a live server, you may want to block your test site from search engines. In a real world situation, use anything except for admin as a username. Using the default username makes your site an easy target for experienced WordPress hackers. Once, you’re finished installation, log in with your new credentials.
STEP 3: ADD SOME TEST CONTENT
Add a few new posts to your blog. I used htmlipsum to fill up a few test posts. Use the visual editor to add a few images to your posts. Add a few categories and tags while you’re at it. Make sure at least one of your posts has a link to another internal post.
STEP 4: SET UP YOUR PERMALINKS
View a post and take a look at your URL. Not so pretty. Head back into WordPress admin to set up pretty permalinks. Select permalinks under the settings menu. I like to use a custom structure of /%category%/%postname%/. This is much more human and search engine friendly.
(1 image wasn't archived)
TECH TIP: PRETTY PERMALINKS
When you set up pretty permalinks, WordPress creates an htaccess file with some MOD REWRITE rules in place. It basically takes your post id’s and turns them into readable URLs. MOD REWRITE is super powerful. If you want to learn more about it and Apache in general, check out Ask Apache.
STEP 5: LOOK UNDER THE HOOD
Let’s take a quick look at our database to see how WordPress works. Open up phpMyAdmin and navigate to your database. You’ll want to browse the table called wp_options.
(1 image wasn't archived)
WordPress stores lots of useful information about your blog within this table, including the siteurl.
(1 image wasn't archived)
Select the wp_posts table and click Browse from the top tabs. If you scroll way right, you can see the GUID field that contains something like http://localhost:8888/testBlog/?p=3. Notice that the GUID for your post with an image attached is the absolute URL to the image.
(1 image wasn't archived)
STEP 6: BACK IT UP
Now that we have a better understand of what WordPress is actually doing under the hood, we need to create a backup of our database before we go breaking everything. In WP Admin, click export under tools. This will export an xml file you can upload directly into WordPress if you lose information. As regular site maintenance, I recommend exporting weekly so that you have back ups in case of a failure.
(1 image wasn't archived)
STEP 7: MORE BACKUPS..
You should also export a gzipped copy of the database from phpMyAdmin. From the root of phpMyAdmin, click the export tab. We want to export the entire database, saving it as a gzipped file.
(2 images from this post weren't archived)
In a real world situation, you would also ensure that you have made copies of your wp-content folder. This is where all of your themes, uploads and plugins are stored.
STEP 8: MIGRATE
Create a new folder in your htdocs folder or the root of your server. Ensure that your file browser is displaying hidden files. You’re going to want to make sure that your .htaccess file is transferred over to the new folder. These files are hidden by default, so I recommend doing this transfer from Coda or Dreamweaver. To turn on hidden files in Coda, go to View -> Show Hidden Files. Grab everything and move it to the new folder.
(1 image wasn't archived)
STEP 9: START FIXING IT
Head to your new URL. Pretty well nothing will be working. We need to update our siteurl in the wp_options field. We’ve got two options from phpMyAdmin, run an SQL query, or find the field and change it ourselves. Since we already know where the field is, we’ll change it ourselves. Head back to phpMyAdmin and browse the wp_options table. Go ahead and update your siteurl now.
(1 image wasn't archived)
Refresh your site. Still nothing. Add /wp-admin/ to your sites URL. Head to Settings -> General. You’ll need to set the Site Address to your new URL. Notice that your WordPress address will be already updated. Head back to your site and you’ll see that there is some stuff showing up now. Things are, for the most part, working. You should notice that both your post containing an internal link and internal image uploaded through WordPress are both broken.
STEP 10: FIXING BROKEN LINKS AND IMAGES WITH SQL QUERIES
On a big site with lots of content, this is a big issue. The fastest way to solve this is to run an SQL query from phpMyAdmin. Select your database from the list on the left and choose the SQL tab. We need to run two queries, one to update the guid field of wp_posts, and one to update any string within the post_content field of wp_posts that contains the old URL. The following two queries will take care of that for us.
UPDATE wp_posts SET guid = replace(guid, 'http://localhost:8888/testBlog/','http://localhost:8888/newTest/');
UPDATE wp_posts SET post_content = replace(post_content, 'http://localhost:8888/testBlog/','http://localhost:8888/newTest/');
Execute the queries. The result is shown underneath the SQL tab. If 0 rows are affected, you’ve done something wrong. If not, were all fixed up! Head back to your site and everything should be working properly.
(1 image wasn't archived)
STEP 11: BREAK IT ONE LAST TIME, AND SECURE IT
This next section is completely optional. By now you’ve installed WordPress and successfully migrated it to a new location or even a new server. You would use the same steps on a production site.
Now I’m going to show you something that I feel should be out of the box with WordPress. FYI, this will not work if you are using WP Multisite. Take a look at your file structure of you WordPress directory. It’s not what I would call organized. Create a new folder in your WordPress directory. I’ll be calling mine wp. This folder name is going to viewable by the public, although in very few situations, so make sure it is appropriate. WP is very generic, I’m sure you can come up with something that better fits your individual site.
Grab all of your WordPress files and drag them into your new folder. Now copy (not move) both index.php and .htaccess to your root folder that you just moved them from. Your site is now very, very broken.
STEP 12: FIX IT… AGAIN.
Open up your index.php. Line 17 contains the following code:
require('./wp-blog-header.php');
We need to change this, as wp-blog-header.php is no longer in the same place. Add your folder to the front of this.
require('./wp/wp-blog-header.php');
Browse to your site and you’ll see that things are now working. Sort of. We need to fix our siteurl one more time. Head back to phpMyAdmin, browse the wp_options table and change siteurl. What used to be http://localhost:8888/newTest/ will now be http://localhost:8888/newTest/wp/.
STEP 13: UPDATE IMAGES
You’ll notice that our images are once again broken. We need to run a more specific query this time to fix this one. We don’t want to add /wp/ to our internal links, but we have to change our image sources. Running the following query from phpMyAdmin will fix your images:
UPDATE wp_posts SET post_content = replace(post_content, 'http://localhost:8888/newTest/wp-content/','http://localhost:8888/newTest/wp/wp-content'/);
This will add the proper src attributes to your images, fixing any broken images.
STEP 14: LOCK IT DOWN WITH HTACCESS
Now that we’ve got a super organized, flexible WordPress installation, let’s secure it. Wp-config.php contains a lot of information you don’t want getting into the wrong hands. To prevent that from happening, open up your .htaccess file that is in the same folder as your core files. We’re going to add in a few lines to lock it down.
As a warning, do not mess with .htaccess unless you know what you are doing. One typo in an .htaccess doesn’t just make a page unreachable, it breaks the entire server. Be careful.
Add the following code after # END WordPress. I should note that # is simply a one line comment when you are writing inside .htaccess files.
# wp-config.php protection
order allow,deny
deny from all
This prevents anyone or any bot from accessing wp-config. Doing so results in a 403 forbidden.
Congratulations, You’ve now got a very flexible, secure WordPress powered website!