Manually Migrate a WordPress Site

Requirements

  • Two servers capable of running WordPress, both providing
    • Command line access (usually via ssh)
    • phpMyAdmin or a similar web admin UI capable of managing SQL databases.
  • Both WPs are installed into the webroot folder (top level, /) or the exact same subfolder (e.g. /blog). If your situation differs you might still succeed with additional steps. For example this tutorial describes a more complex process.

Migrating files & data

Database

  • Log into the source machine's phpMyAdmin

  • On the "Databases" tab, select (click) the database you want to export. Take note of "Collation" and "Privileges".

  • On the "Export" tab, choose the "Quick" export method, and the SQL format.

  • Save the file.

  • Log into the target machine's phpMyAdmin

  • On the "Databases" tab, create a new database. Choose the same "Collation" type as on the source machine.

  • Take note which user will access the database

  • On the "Import" tab, select the previously downloaded file to import. Don't adjust any other settings but make sure the format is SQL.

WordPress files and folders

  • Open a (remote) shell on the source machine, navigate to your WordPress folder.
  • Zip everything up, e.g.: zip -r wp.zip .
  • Use scp to copy it straight to the target machine: scp wp.zip user@target:~

You are done on the source machine now.

  • Open a (remote) shell on the target machine and unzip the file to its target directory, e.g.:
    unzip wp.zip -d /var/www/html/new_wp (you might need to do this as a different user, e.g. www-data).

Preparation

On the target machine, locate your new wp-config.php. Edit to replace the following entries:

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'new_db' );

/** Database username */
define( 'DB_USER', 'new_db_user' );

/** Database password */
define( 'DB_PASSWORD', 'newPa$$word!' );

/** Database hostname */
define( 'DB_HOST', 'new.database.host:3306' );

While you're at it, scroll a little bit further down and renew the "Authentication unique keys and salts" - there's a link that makes this very easy.

In my opinion this should be enough, but it isn't. The old site URL is still coded into several database entries. Since the web UI is broken until this is fixed, we have to do it manually:

  • Permanently override (?) the site URL:
    • Edit wp-config.php
    • Just above /* That's all, stop editing! Happy publishing. */, add:
      define('WP_SITEURL', 'https://' . $_SERVER['SERVER_NAME']);
      define('WP_HOME', 'https://' . $_SERVER['SERVER_NAME']); 

      This definition will use the server name defined through your server software (e.g. Apache) as base URL. If your WP is in a subfolder, the first line should be e.g.

      define('WP_SITEURL', 'https://' . $_SERVER['SERVER_NAME'] . '/subfolder');

      instead. (source)

I suppose alternatively one could also edit the database entries. phpMyAdmin has a search option. I can quickly find two likely entries in the "options" table, but since this WP is running on a temporary domain name I will leave it for now.

You should be able to visit the new wordpress install now. Make sure the new domain is used everywhere and nothing links to the old site. It might be best to disable the old site for now if you haven't done so yet.

If you have defined a static home page

  • Log into the new WP-admin dashboard
  • Under Settings => Reading, select a different homepage, and Save Changes.
  • Change it back to what you want, and Save.
  • Did it work (make sure your browser is not caching anything)?

Also check Settings => General and Settings => Permalinks

When using your browser to test the new site, make sure it doesn't cache anything for the time being.

Troubleshooting

If the site still doesn't work fully try to find files that still contain the old domain. Open a (remote) shell, navigate to the new WP install's root folder:

grep -r old.domain.name

This will give you an overview. Just the filenames:

grep -rlm1 old.domain.name

Replace these strings at your own discretion. The nano editor is usually available and easy to use.

If that still doesn't fix everything, find database entries that contain the old domain.
phpMyAdmin has search and edit functions.

Lastly

Once you moved the new install to its final place, you might want to edit the database entries still containing the old site URL. In theory this should allow you to remove the previously added define()s from wp-config.php.

If you remove the old WordPress install, remember to also remove/empty the database.