Migrating a WordPress website from Linux to Windows

This post describes the process of migrating a WordPress website from Linux to Windows. I recently had a client who asked me to host their WordPress website on my Windows Server environment. The site was initially hosted on a Linux platform. There are many useful resources out there on the web that indicate what steps to take when migrating a WordPress website but since I’ve had to dip into bits here and bits there, I thought I’d consolidate my personal recipe into a quick blog.

I was given a zip file containing an FTP download of the whole site, and a SQL export of the database. Here’s what I did, step by step.

Step 1 – Amend Database Configuration in wp-config.php

Find wp-config.php in the root of the website. Look at these lines:

define('DB_NAME', 'AlkaneDBName');
/** MySQL database username */
define('DB_USER', 'AlkaneDBUser');
/** MySQL database password */
define('DB_PASSWORD', 'AlkaneDBPassword');
/** MySQL hostname */
define('DB_HOST', 'www.xxx.yyy.zzz');

These four values contain credentials and the location of the MySQL back-end for our WordPress database. You can leave the DB_NAME, DB_USER and DB_PASSWORD as-is for now. As for the DB_host, you’ll want to change that to either ‘Localhost’ or the IP address of your MySQL server. Save it once done.

Step 2 – Create MySQL Database

Now, I use a Plesk interface, so I log into my control panel and I select ‘Databases’ and then create a new MySQL database. I call it ‘AlkaneDBName’ as defined in DB_NAME. I then create the admin user for the database with the credentials defined above – the username is ‘AlkaneDBUser’ (from DB_USER) and the passsword is AlkaneDBPassword (from DB_PASSWORD).

Once you’ve created your database, import your SQL script. Open the web admin console (PhpMyAdmin in my case), click ‘Import’, brwse to your .SQL file and click Go. This should import your database.

Step 3 – Upload the website files

Upload the website to your HTTPDocs folder on the web server. Go to your URL and then BOOM! Voila! It works!! Or does it?

Step 4 (Optional) – Update the database connection password

Unfortunately things didn’t go quite so smoothly for me. Firstly, the original password (DB_PASSWORD from web-config.php) provided to me appeared to be too complex and I kept on receiving the error:

“Error in establishing database connection”

The reason I knew this is because I used the following test php file (I called it test.php, uploaded it to the server and ran it)

<?php
$link = mysql_connect('localhost', 'PutUsernameHere', 'PutPasswordHere', 'PutDatabaseNameHere');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
echo 'Connected successfully';
mysql_close($link);
?>

I used a process of elimination to decipher whether it was the username, the password or even the database name that it didn’t like. And it turned out to be the password.

So, surely it works now? Well the website displays which is good. But I cannot log into the WordPress control panel! “Jiminy Cricket”, i mutter to myself. The password for the admin panel was very (i mean VERY) strong too. So I thought I’d reset it first to something still strong, but not quite as strong. It worked like a charm. Here’s how I did that:

Step 5 (Optional) – Update the WordPress admin user password

In PHPMyAdmin, find the table wp_users. Click on the table name, click on the SQL tab, and then click Go. This should show you all users in the table. Luckily mine only had one user. So I clicked the small pencil next to the row to open edit mode. I then changed the value of the user_pass field to a new password. But wait!! You can’t simply change the password like that. You MUST select MD5 from the ‘Function’ column so that the password gets encrypted. Otherwise it won’t work. This solved my logging in problem. Yippee! Done!! Or was I?

Step 6 (Optional) – Configure Default Document for IIS

No. Whenever i tried to load www.exampledomainname.com I received an error 404. I needed to append ‘index.php’ onto the end to make it work each time. The easiest way to fix it was in the web.config file which I created from scratch and uploaded to the root of my website. To fix this issue it looked like this:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<defaultDocument>
<files>
<remove value="index.php" />
<add value="index.php" />
</files>
</defaultDocument>
</system.webServer>
</configuration>

Done, finally? No!

Step 7 (Optional) – Remove index.php from Permalinks

The permalinks didn’t work properly. Whenever you clicked on a link in the website it loaded a URL which looked like this:

http://www.exampledomainname.com/index.php/yyyy/mm/dd/post-name/

This would obviously mess up any links in search engines, on user’s desktops, and it looks incorrect. This can be fixed by following instructions in this link. But in brief, it means that your resultant web.config should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<defaultDocument>
<files>
<remove value="index.php" />
<add value="index.php" />
</files>
</defaultDocument>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{URL}" negate="true" pattern="\.axd$" />
</conditions>
<action type="Rewrite" url="index.php" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

Note that the Permalinks page is now under Settings > Permalinks and not Options > Permalinks (if you’re using a later WordPress, that is). The following line:

<add input=”{URL}” negate=”true” pattern=”\.axd$” />

ignores any requests for HTTP Handlers (if you’re using AJAX throughout your site in .Net pages, as I was!) You’ll notice that if you don’t include this line that some AJAX page controls will screw up!

Step 8 (Optional) – Configure FastCGI

So everything was running properly (at last!). But the speed of the site (the website and the admin interface were the same) was slow. This vastly improved by configuring the site to run as FastCGI as opposed to a CGI Application.

To configure this in Plesk, I go to Web Hosting Settings and then scroll down to the PHP setting. My version is set as 5.2.17 and I change the ‘run as’ to ‘Fast CGI Application’.

Finally, we’re done!

Because I’m a helpful hoster, I decided to upgrade the instance of WordPress to the latest version (version 4). To do this, I adjusted the permissions on the wp-content and wp-includes folders and added the following line to my wp-config.php file:

define ('FS_METHOD', 'direct');

This enables users to directly upgrade Wodpress via the admin interface (saving me support calls hopefully!).

Oh, and finally finally. In this post I was performing a migration but the URL was staying the same. If the URL was changing, I would have probably needed to change the siteurl (optionid = 1) and the home (optionid = 37) fields in the wp_options MySQL table. As well as any hard links in the wp_posts table. But there are tools out there to automate this process.