When working with a development site for testing, a common question is how to migrate. What is a quick way to copy a site to a development copy and vice versa?
For me, I often use WP-CLI for this purpose. WP-CLI is the Command Line Interface for WordPress. It allows you to manage your WP site completely from the command line. It is very powerful and very fast. No waiting for page loads in admin panels when using WP-CLI.
When I started using WP-CLI, you had to install it yourself, which could be somewhat intimidating for someone who doesn’t normally work with command line tools. But today, many hosts include this as already installed and ready for your use. You only need to know how to connect via SSH (Secure SHell). Personally, I use PuTTY, but you can use whatever tool suits you.
Here are the steps that I use to make a development copy of my live site:
Prerequisites: As mentioned above, you will need two things – WP-CLI and SSH access. At some point, I may write up a tutorial on each of these, but for now there are plenty of existing tuts on the webernet. Just use Google and you’ll see what I mean.
Make sure you’ve got a copy of your dev site’s wp-config.php and .htaccess files. Your dev config should use the same db prefix as the live site (i.e. “wp_” or whatever you use) but in a separate database. Keep a copy of the dev wp-config.php and .htaccess somewhere outside of the filesystem (i.e. locally) so you can copy them later. We’re going to wipe everything out on the dev’s filesystem, so we want to be able to drop these in later to set up the dev site.
- wp db export
- zip -r my_export_file_name.zip *
- rm (name of sql file you exported)
The “wp” command is WP-CLI. Here I am exporting the entire wp database to a sql file. It will export to the file system, which I am then using “zip” to compress so we can move the entire thing to the development server. The sql file will zip up with all of the other site files. When zipping it up, the “-r” command is “recursive,” so it will include all of the folders and sub folders. Then I give my zip file a name and use the wildcard * to indicate that I want every single file.
IMPORTANT: the “rm” command “removes” (essentially: deletes) the sql file you exported. Do not miss this step – we don’t want to leave the database export laying around. If you don’t specify a filename (which we didn’t), there are some random characters added to the filename so it’s not like someone is going to instantly grab this off your site. But don’t be foolish and trust that you can leave it there – make sure it’s deleted as soon as you’re done. (Note: if you’re using this process just to back up your site and data, you could at this point download your zip file, FTP would be preferred. Then delete the SQL and zip files when you’re done.)
- (keep a copy of your dev site’s wp-config.php and .htaccess for use later)
- wp db clean
- rm -rf *
- wget https://mysite.com/my_export_file_name.zip
Now I use “wp” to clean the database on the dev site so it’s completely empty. I use “rm” to remove all files on the file system (-rf recursively removes all files AND folders), with the wildcard * to indicate we want to wipe everything. Then “wget” gets the zip file from my live site. This leaves you with an empty WP database and a completely empty file system, so remember that you need to keep a local/offsite copy of your dev site’s wp-config.php file.
- rm my_export_file_name.zip
IMPORTANT: Now I go back to the live site to remove the zip file. This is the same as when we removed the sql file in the first step. Don’t forget this part and leave it sitting around on your server. That’s a security risk.
- unzip my_export_file_name.zip
- (upload/copy original wp-config.php and .htaccess for dev)
- wp db import (name of sql file)
- wp search-replace https://mysite.com https://mydevsite.com
- rm my_export_file_name.zip
- rm (name of sql file)
- (OPTIONAL) wp plugin install disable-emails –activate
In this last block, we unzip the file we picked up from the live site. This puts an exact copy of everything we had on the live site on our dev system. Then we copy our original dev wp-config.php and .htaccess files to connect to our dev database and have our dev URL in the .htaccess. Run the WP-CLI db import. Now the db matches the live site. Use WP-CLI’s search-replace command to replace all instances of your live site URL with the dev site URL. This handles not only the site URL in the WP options, but every instance throughout the site – content, menus, etc. Then remove the zip and the sql files since we don’t need them anymore.
Note on Optional Step 7 – this is optional but recommended. This installs the plugin Disable Emails which will totally shut down emails on your server. You may have email testing you want to do, but keep in mind that you’ve just made a total and complete copy of your live site including your live site users. If you don’t want emails going to them from testing, this is a critical step. If you have users and you’re going to be doing email testing, then there are a couple of options you can do. First would be to remove all the live users from your dev db. An alternative would be to change all of the emails to a single email. You can’t do that in WP itself, but you CAN do it directly in MySQL with “UPDATE wp_users SET user_email = ‘firstname.lastname@example.org’;” That will set all user email addresses to whatever value you set in the SQL query. Keep in mind this is optional, and for me, I only do this if I need to test emails. Otherwise I just use the Disable Emails plugin.
THAT’S IT! You’re done. You’ve now set up an exact copy of your live site on a development server.
This may seem like a lot of steps, but it’s really only tedious the first time if you’re unfamiliar with the steps. Once you do this once or twice, it will become more comfortable. I’m not kidding when I tell you that when I spin up a development copy of my site for testing using this method takes less than 2 minutes – and that includes waiting for zipping and file transfer.
Then you can use WP-CLI for running updates to WP core, themes, plugins, etc, and testing. Often, if I need to do a lot of testing with potentially the need to rollback, I will make a quick backup using some of the steps above to create a “restore point” on my dev system. That way I can quickly restore the dev site to a particular state without having to complete all steps to restore from the live.
Two important points to emphasize: 1. DO NOT leave the zip and sql files laying around on a server that is open to the world. It’s fine for making your copies and moving things around, but delete them (or download them) when you’re done. 2. Start this process with a wp-config.php and .htaccess file for your dev system. This can be from an existing WP install that you delete, or can be started fresh; but it’s important to have these and make sure that you are using a separate database for dev vs live. If you miss this step, your dev system could potentially be writing to your live site’s database and that would be bad.
Side benefit: You should be able to see how you can use the first part of this to easily make complete backups of your live site. Drop a few steps (like search-replace, and changing the config files) and you can also quickly and easily restore your site from a full backup. Because it’s CLI, you can set up cron jobs on the server to automatically handle your backups on a schedule.