Hosting is one of those things that you tend to buy and then forget about, like buying an electricity provider. It just works and you forget about it. There are always specific cases where you may need someone more specialised, but for the most part, it just works. But every now and then, you there comes an event where you decide that a change is in order. My current hosting provider was up for renewal (and they were expensive), so I decided to migrate to Google Cloud Platform.

Note, this takes a couple of weeks to execute, including the domain (DNS) transfer, so keep this in mind. I finished my migration with about a week to spare.

Caveat Emptor: Warnings before you commence on this quest

  • This is my personal blog and opinion and doesn’t represent the opinions of my employer nor a detailed study into your requirements. Take this into account when you read my instructions here.
  • Following this deployment guide will make you responsible for your WordPress instance. This assumes that you have the capability to manage it (i.e. support it from an infrastructure and code perspective). If you do not, this may not be for you (however you can try it bar the final service cut over and shutdown of old service for training purposes).
  • High availability for my personal blog was not a priority. Low cost was.
    • Looking at the choices available, I used f1-micro and later e2-micro instances (using shared cores). The f1-micro VM is within Google Cloud’s free tier and is fine for WordPress development. With a little more image manipulation as well as server maintenance, I moved to e2-micro as tuning the server to economise memory was not a worthwhile endeavour.
    • If high(er) availability was a priority, I would probably create a load balancer, managed instance group, health checks, separate out persistence (using Cloud SQL), but this does cost a little bit more.
  • Disaster recovery comes in the form of WordPress export as well as a machine image (which I recommend to rebuild the VM in the case an upgrade / patch goes wrong).
  • Certbot is a free SSL software tool to deploy on your VM to enable HTTPS using Let’s Encrypt certificates. It’s really nifty.

Step One: Preparation for migration and check your requirements and  budget

  • Select your future cloud provider (in my case, Google Cloud Platform):
    • Analyse your current cloud provider / service provider and work out what you require in terms of equivalent compute, storage, network, and support.
    • Going fully managed if support is really important: If you do not want to rely on community support and/or are not comfortable with development / debugging a LAMP stack application, perhaps GCP is not the right choice for you. A fully managed solution like Kinsta or WPEngine are good choices.
  • Google has a recommendation for various WordPress deployment scenarios here.
    • Depending on your load requirements (especially if they are large), you may need to consider a deployment on Kubernetes or App Engine. My blog isn’t that frequented, so I selected a Google Compute Engine based approach.
    • Google has a Marketplace / Click to Deploy template ready for you. It will step you through the process and deploy it pretty much in seconds.
  • Check your pricing: In Google’s cloud, for most basic needs the micro / free tier was a good fit for me. Note that the free tier only applies to certain regions, so make sure you select this when you set up your instance.

Step Two: Prepare your existing host provider for migration

  • Domain ownership: If your domains are owned by the current hosting provider and you want to transfer them out as well, you can perform a domain transfer to Google Domains. This is optional for just a WordPress deployment, but since I’m also deploying G-Suite for my domain, this was a good choice for me since the setup becomes one click too (for all G-Suite apps and email). This may take up to a week to execute, so keep this in mind.
  • Backup: There’s a fantastic WordPress plugin called the All-in-One WP Migration. It does pretty much what it says on the tin, downloading assets, code, themes, plugins, everything you need to migrate WordPress into a zip file that you can then restore on a new WordPress installation. Download this zip file and keep it safe.

Step Three: Setup the target server and start testing

  • Deploy the new WordPress instance using the Google Marketplace link. Select your compute instance type and region. For the free tier, make sure you select the right region and compute instance type.
    • Note down the usernames and passwords generated by the deployment script. Store it somewhere safe in case you need to rebuild your instance (Google stores it in metadata but you might lose if it you restore from snapshot).
      • Lesson Learnt: Take down your metadata / access details or recreate them on the new instance before you blow away the old instance…
    • Go directly to your WordPress instance and secure it with an account and password. Also, patch the operating system (with the usual ubuntu sudo apt-get update and sudo apt-get upgrade commands).
    • Cool tip: I deployed it to a larger instance type for testing and then downsized AND moved region after. You can do this by stopping the compute instance and taking a snapshot of the persistent disk. You can then create a new compute instance from the snapshot and change region and instance type accordingly.
  • Reserve Static IP: Assuming you are using a mono-instance deployment (that is no load balancer and multiple machine scenario), then you need to reserve a static IP. Note it down as you will need it soon.
  • Restore your WordPress deployment: Install the All-in-One WP Migration plugin on your new WordPress.
    • Your newly minted WordPress instance will likely stop working. This is normal.
    • Stop the server and take a backup by a snapshot.
  • Test your WordPress migration: On first load, you may be dismayed that your site isn’t working. This is normal, since the plugin migrates your WordPress instance as-is. There are a couple of steps you need to do in order to get it working again.
    • Change site URL temporarily to the reserved static IP:  Follow this WordPress codex guide and follow the edit wp-config.php section. I recommend this, since once you do the DNS update to the new IP address, you don’t need to alter the WordPress database. The php directives will override the settings in the wp_options table and you can uncomment them to do your service cutover.
      • Lesson learnt: There are a lot of pages on the internet telling you how to move URL, move IP address etc, but most of these are related to changing domain name. In this case, you will need update your WordPress database using SQL (notably on the wp_options table). Don’t just blindly execute Stack Exchange code into your WordPress Database! Read up the WordPress Codex first, I cannot stress this enough.
    • WordPress still not working? Other minor problems? Yes, there may be a few:
      • Re-establish .htaccess file: The migration plugin doesn’t move hidden files like your .htaccess file. Look at this guide to restablish it. If you update your permalinks setting, this will also initialise it.
      • Broken theme / WordPress general weirdness: Some themes are tied to older WordPress versions. On upgrading WordPress, you may find your entire site stops working. Now, you need to start debugging. Turn on logging and tail -f those logfiles and have a look around at what is happening.
      • Check your PHP memory limits: Depending on the complexity of your WordPress deployment, you may hit PHP memory limits. You can set this in the wp-config.php file as well.
      • Get wp-cli: OK, you might have ignored my advice and run random Stack Exchange scripts on my Database. To fix this, you can roll back your snapshot, or use wp-cli which has a fantastic search and replace function. Clone the git repo, install it, and give it a try.
    • Final WordPress touches:
      • Complete Google Analytics integration: Use a header plugin to insert the tracking javascript.
      • Update your theme and make the site pretty. I didn’t have enough time to replace my old incompatible theme, so I made some minor changes to a standard WordPress theme as an interim measure.
  • Setup billing and budgets in GCP: With the cloud you could end up spending a lot of money, so it is a good idea to set up some billing and budget limits. Don’t get caught out by large bills!

Step Four: Domain Transfer in complete. You may not get notified of this so keep an eye out or a calendar notice in your diary.

  • Setup Google Domains to point to your old service provider: This is essential, because if you don’t do this, your site will effectively be undiscoverable (including to Google Search). This is a sure fire way to destroy your referencing. Update A and CNAME records to your old service to keep yourself discoverable on the web.

Step Five: Cutover to new service

  • Final service testing: Check that the target server is functioning as required.
  • Final pre-cutover golden image backup: Stop the compute instance and take a snapshot.
  • Start the compute instance and retest by accessing the IP address in a browser.
  • Update the A and CNAME records in Google Domains to the new server IP address
  • Update the wp-config.php file with the domain name of your site, clear the cache of your browser, and your site should be functional.

Step Six: Shutdown old service

  • Shutdown your old service and turn off all auto-renewals. Confirm this with the support staff of your old provider and send them a note of thanks. They have been serving you well over the past few years after all!

Note that security of your instance is now your responsibility. If you are moving away from a managed service, this may require you to change your habits somewhat. Periodically update your WordPress instance to keep it secure. Periodically take snapshots and update the OS as well.

That’s pretty much it! There were a couple of gotchas that I found painful (i.e. I got wrong first time):

  • The Google free tier only applies to micro instances in certain regions.
  • If you do try a larger compute instance keep an eye on your budget.
  • If you are keeping your domain name the same, just override it in wp-config.php. Don’t touch the WordPress database!
  • Keep your DNS settings up to date during the entire migration.