WordPress migration

As the most technically-minded readers might have noted, this blog is running on WordPress. Although there are lots of alternatives, none have a comparable user base and availability, so I have picked this blogging system when I started, and I must say I have not met any glaring issue so far. It has all been working fairly well for what I’m doing.

On the other hand, I had other unrelated issues with my hosting provider, which eventually pushed me to try going somewhere else. This involved migrating this whole blog from the old provider to the new, which I thought would be a no-brainer given how common the situation must be. Well, it turned out to be a much more sensitive, error-prone and finicky task than I expected, and so in the interest of other (and future me!) here is how I finally managed it.

The problem

I wanted to minimize downtime as much as possible. You might say that it was something of an academic concern, it’s not like this blog attracts thousands of readers a day… But I value the readers I do have, and the search engines also do not like stuff disappearing. So the idea was to run two blogs in parallel for a while, check everything was running smoothly, and then switch as quickly as possible from the old to the new.

For a classic website, composed only of static pages, it would have been relatively easy:

  • copy the website’s files to the new provider
  • create a subdomain for it, check that it works
  • point the real subdomain to it, and voilĂ , migrated

Unfortunately WordPress makes it a bit more complicated. There are two fundamental problems here:

  • a WordPress blog is dynamic, generated from a database that you also need to migrate
  • the URL of the blog itself is a parameter of WordPress. You can’t just move the files around and expect it to work – you need to adjust this parameter, and everything possibly generated from it

As a computer scientist the latter was particularly puzzling to me as a design decision, but hey, it’s not like I’m motivated to write my own blog engine.

If you search the web, you’ll find a lot of guides about how to do that migration, with a variety of methods among which I’ve found very few that work reliably. The key insights I’ve gained are:

  • Do not rely on plugins and the web interface to do this. It might be possible, it may even work well for a small test, but it relies on a myriad of planets aligning just right
  • Do not be afraid of the command line. There is this tool called wp-cli which solves a lot of the problems people would have you install their plugins for, in a much cleaner and reliable way. Especially, this works even if you have broken the web interface somehow, and you will break it in the process, almost inevitably

The process

So you want to migrate your cool blog accessible at https://your.domain.net/a/blog/ from oldhost to newhost.

One possibility, if the old and new hosts are configured exactly in the same way, is to just move the file and the database over. However this was not the case for me, and I suspect for many people. In both cases the hosting provider packages WordPress installs with its hosting solution, and if you want to take advantage of this, you cannot just move everything like that. It is also a solution that carries great risks of being subtly broken in ways hard to diagnose, especially with regards to the database.

Therefore, I decided to rather re-build the whole blog on newhost:

  • Create a subdomain yourhidden.domain.net, point it to newhost
  • In newhost, create a new blog https://yourhidden.domain.net/a/blog. Bring in plugins, themes, etc. Themes are located in wp-content/themes, and normally designed to be moved like that. Plugins I figured were better reinstalled from scratch on the new server (detected a few abandoned plugins like that, which is a nice bonus).

You have a blog on newhost, but it’s still missing content.

  • WordPress has an export function, which is one of the few things that work equally well from the web interface (Tools/Export) or wp-cli. Export the old blog to a file
  • Import it into the new blog using wp-cli (the web interface might not cope with the volume or the time it takes to import): wp import <file> --authors=create
  • Make a search and replace using wp-cli on newhost, so that no url to the old blog remains (because these are imported without a change by the import command). This command has a lot of options, but this should be something like: wp search-replace https://your.domain.net https://yourhidden.domain.net

At that point you should have the same content at both ends: https://yourhidden.domain.net/a/blog and https://your.domain.net/a/blog. Check thoroughly! In my case I was importing from a multisite blog, which is currently broken; I had to copy wp-contents/uploads/sites manually to get all the images back. There were a few settings that were not imported: menu bars, date format, etc. The new site is not live yet, so you can take your time.

Then when you are happy with the result, switch things up:

  • Change the url of the new blog using wp-cli again, this time from https://yourhidden.domain.net to https://your.domain.net. At this point, your blogs are in a strange space. If you connect to https://yourhidden.domain.net/a/blog, you will connect to newhost, but WordPress running there will actually redirect you to https://your.domain.net/a/blog, still on oldhost! So technically you cannot really carry out administrative tasks any longer on the new blog, except by using wp-cli at newhost
  • Point your.domain.net to newhost, and let DNS propagation happen. You are safe here: whatever the DNS state that a reader has, he will reach either the new or old blog which are nominally identical. If you’re really paranoid you could put them both in a read-only state or even maintenance mode in the meantime

Congratulations, you’re live at newhost!

However, no check is sufficiently thorough, and you will probably need to have access to the old site to look things up for a while. It is quite easy however, given what we did before:

  • point yourhidden.domain.net to oldhost
  • using wp-cli on oldhost, change all urls from https://your.domain.net to https://yourhidden.domain.net

Now you have made a complete switch: the old blog is accessible on oldhost at https://yourhidden.domain.net and the new blog is accessible at https://your.domain.net.

Note that in the process, you have also learned how to back-up your blog: the exported file, together with whatever you had to manually copy over, really are the most valuable parts of your blog.

Leave a Reply

Your email address will not be published. Required fields are marked *