WP Engine to Pantheon Migration

Recently I helped a customer move their site from WP Engine to Pantheon. Pantheon’s platform is quite different then WP Engine. During the process I wrote a script to automate the deployment process which allowed me to quickly resync the sites from a WP Engine backup to Pantheon.

Prepare sftp with Rclone and Terminus for WP-CLI

The first step is to add the Pantheon live site sftp info to Rclone. This allows the uploads folder to be incrementally synced from a WP Engine backup snapshot to the Pantheon live site. Terminus is Pantheon’s way to interact with WP-CLI. Terminus needs to be installed and authenticated before it can be used. Terminus handles the database import and plugin configurations.

Local git setup for themes and plugins

Pantheon requires a deployment strategy for themes and plugins. You can’t just upload files directly to the live site. Instead you need to activate all 3 Pantheon sites: test, dev and live. Once the sites are active, clone the test site git report to a local folder matching the pantheon_sitename in the below script. The last part of the script syncs the themes and plugins from the WP Engine snapshot over the local git repo. After running the script you’ll need to manually add all theme/plugin changes to git and deploy to Pantheon’s test site. Within Pantheon then deploy from test to dev and from dev to live as is their recommended workflow.

From WP Engine snapshot to Pantheon live site

With all the preparation in place, deploying from WP Engine to Pantheon is as simple as generating a fresh WP Engine snapshot and feeding that into the pantheon-wpe-deploy.sh script.

#!/usr/bin/env bash

#   Migrate site from WP Engine backup snapshot to Pantheon via SFTP (Rclone)
#   `pantheon-wpe-deploy.sh "<wp-engine-snapshot>"`

preview=true                                         # If "true" then use Pantheon live urls and disallow search privacy
wpe_url="https://sitename.com"                       # WP Engine's live url
pantheon_url="https://live-sitename.pantheonsite.io" # Pantheon's live url
pantheon_sitename=sitename.live                      # Pantheon site name for Terminus
rclone_remote=sftp-sitename                          # Rclone name for Pantheon live sftp 

backupformat=$( echo $backup_url | perl -n -e '/.+\.(.+)/&& print $1' )

# Generate fresh snapshot directory
timedate=$(date +'%Y-%m-%d-%H%M%S')
mkdir -p restore_$timedate
cd restore_$timedate

wget -O restore_$timedate.out $backup_url

if [[ "$backupformat" == "zip" ]]; then
  mv restore_$timedate.out restore_$timedate.zip
  unzip -o restore_$timedate.zip
  rm restore_$timedate.zip

# Finds WordPress path
wordpresspath=$( find * -type d -name 'wp-content' -print -quit )

# Migrate uploads if found
if [ -d $wordpresspath/uploads ]; then
  echo "Syncing: $wordpresspath/uploads to ${rclone_remote}:code/wp-content/uploads"
  rclone sync $wordpresspath/uploads ${rclone_remote}:code/wp-content/uploads --size-only -v

# Upload WPE database backup to upload folder
echo "Uploading database $wordpresspath/mysql.sql to ${rclone_remote}:code/wp-content/uploads/mysql.sql"
rclone copyto $wordpresspath/mysql.sql ${rclone_remote}:code/wp-content/uploads/mysql.sql -v

terminus wp $pantheon_sitename -- db reset --yes
terminus wp $pantheon_sitename -- db import wp-content/uploads/mysql.sql
terminus wp $pantheon_sitename -- cache flush --skip-plugins --skip-themes

# Removed uploaded database backup
echo "Removing ${rclone_remote}:code/wp-content/uploads/mysql.sql"
rclone deletefile ${rclone_remote}:code/wp-content/uploads/mysql.sql

if [[ "$preview" == "true" ]]; then

   # Search and replace URLs
   terminus wp $pantheon_sitename -- search-replace $wpe_url $pantheon_url --all-tables --report-changed-only --skip-plugins --skip-themes

   # Disallow search privacy
   terminus wp $pantheon_sitename -- option update blog_public 0 --skip-plugins --skip-themes
   terminus wp $pantheon_sitename -- plugin deactivate login-recaptcha easy-wp-smtp
   terminus wp $pantheon_sitename -- plugin activate disable-emails


# Sync themes and plugins to local git repo
if [ -d ${wordpresspath}/themes ]; then
  rsync -a --delete ${wordpresspath}/themes/ ../${pantheon_sitename}/wp-content/themes/
if [ -d ${wordpresspath}/plugins ]; then
  rsync -a --delete ${wordpresspath}/plugins/ ../${pantheon_sitename}/wp-content/plugins/
if [ -d ${wordpresspath}/mu-plugins ]; then
  rsync -a --delete ${wordpresspath}/mu-plugins/ ../${pantheon_sitename}/wp-content/mu-plugins/