How to Migrate and Sync Drupal Sites with Drush
If you thought Drush is amazing for installing and updating Drupal modules real quick, you should see it in action when it comes to migrating sites or keeping multiple sites synchronized. If you don't know what Drush is, you can read this introductory tutorial that will get you set up. If you want to know how to use some of the basic Drush commands, you also have this tutorial that gets you up to speed.
In this tutorial, you will learn how to use Drush to more effectively migrate sites from one VPS to another, to manage more than one site and to synchronize easily between them. It assumes that you are running your own cloud server, have Drush on it, and have already installed a Drupal site.
When performing actions with Drush, ordinarily you have to type the commands while being in a Drupal folder. When having to deal with only one Drupal installation, this is not a problem. But there are cases, which we will see in this tutorial, where you'll need to manage multiple sites. Luckily, Drush has an amazing features called aliases.
Drush aliases are a simple set of configuration that allows you to reference Drupal sites from anywhere in your server's folder structure by using a shortcut of the following format @site. Before being able to use these shortcuts though, you'll need to configure the respective alias. To do this, and if you don't have one already, create a file called aliases.drushrc.php in the .drush folder that resides in your server's root folder:
Here, you have to create a php opening tag,
<?php, for the file and below copy the following array declaration:
$aliases['site1'] = array( 'root' => '/var/www/drupal_folder', 'uri' => '188.8.131.52/drupal_folder', );
Let's see what this means. The array key site1 is going to be the shortcut name by which you'll be able to reference this site via Drush (you can replace it with whatever you want). Inside the $aliases array, the root key should have a value as the directory of your Drupal site whereas the uri key should have a value as the URI of the site.
In this example, I used the IP address of a dummy VPS. You should replace that with yours or with your domain name. Make sure that this is referencing the cloud server you currently are on and not a remote one (we'll cover that in a bit too).
Save the file, exit, and the alias is set. To test it out, navigate to a folder that is outside of your Drupal site and run the following command:
drush @site1 status
Now you should get the regular status information about the site you just referenced in the alias. And you can use this shortcut also with other commands.
Now that you know how to reference sites, we can look at migrating (copying) a site from one folder to another using Drush. Let's say you want to move @site1 from /var/www/drupal_folder to /var/www/drupal_folder2.
First, you need to create a new alias for this future installation. For this, like always, edit the aliases.drushrc.php file:
Here, you need to create below two aliases, both with the same format. Just copy-paste the old one and make the appropriate changes:
$aliases['site2'] = array( 'root' => '/var/www/drupal_folder2', 'uri' => '184.108.40.206/drupal_folder2', );
Save the file and exit. If you run drush @site2 status, it will not work because obviously the folder not only does not contain a Drupal installation, but it doesn't even exist. So let's create it:
In order to prepare for the new Drupal installation, you'll need to create a new database as well. So login to your MySQL through your preferred way and create a new database, making a note of the access username and password. If you are unsure how to do this, read the tutorial that shows how to deploy a Drupal site with Drush.
Now that your database is set up, you can proceed to migrate the site. To copy all the codebase from the first folder to the other, run the following command:
drush core-rsync @site1 @site2 --include-conf
What this did was copy all the files from drupal_folder to drupal_folder2, including the settings.php file because of the --include-conf option. If you run the command without this last option, the settings.php file is not included in the copy, which is a great feature as you don't need this file being copied when synchronizing sites.
Now, edit this newly copied settings.php file in the drupal_folder2 copy and change the database information to reflect the new database you just created.
In this file, you need to make changes to the following block of code to reflect your own database information:
$databases = array ( 'default' => array ( 'default' => array ( 'database' => 'your_db', 'username' => 'your_username', 'password' => 'your_password', 'host' => 'localhost', 'port' => '', 'driver' => 'mysql', 'prefix' => '', ), ), );
Save the file and exit. Now you can also migrate the database using Drush because it knows that the site in the drupal_folder2 now uses this database, even if it's currently empty. All you need to do is run the following command:
drush sql-sync @site1 @site2 --create-db
This will drop the tables in the database associated with @site2 (the one that is currently empty) due to the --create-db option and insert the ones from the database associated with @site1 - your original Drupal installation. So now you have 2 exact replicas of the same site.
You may run into the following error message (with the applicable credentials):
ERROR 1044 (42000) at line 1: Access denied for user 'your_username'@'localhost' to database 'your_db'
If this is the case, make sure that your user has the required privileges.
Log into MySQL (
mysql -u root -p).
Grant the following privileges:
grant all privileges on your_db.* to your_username@localhost with grant option; grant reload on *.* to druser2@localhost; flush privileges;
Synchronizing Drupal Sites
Now that you have a duplicate of your original site (@site2), you can use it for development work. If you make codebase modifications to it, you can use the core-rsync command to sync the files with the original (@site1):
drush core-rsync @site2 @site1
Obviously, you would not want to copy the settings.php file again, which prevents making database changes again. Next, to sync the database as well, run the same sql-sync command:
drush sql-sync @site2 @site1 --create-db
In most cases, it's recommended that the receiving database is emptied before the copy (using the --create-db option) to avoid conflicting configuration saved in the database that will then cause problems.
We've seen how easy it is to handle multiple sites on the same server, but what if you have multiple sites scattered across multiple servers? For Drush, the difference is in the information you provide in the aliases. However, in order to work on remote hosts with Drush, you'll need to set up SSH keys between the two servers and have Drush installed on both of them.
- You can learn how to quickly set up Drush in this tutorial
- You can learn how to quickly set up SSH keys in this tutorial
After you've gone through those steps, let's see how to configure the aliases so you can connect remotely. Like always, open and edit the aliases.drushrc.php file on the first server (the one you've been working on before):
And let's create a new alias for a site on a remote server. Copy the following code below and replace appropriately with your information:
$aliases['site3'] = array( 'root' => '/var/www/drupal_folder3', 'uri' => '220.127.116.11/drupal_folder3', 'remote-host' => '18.104.22.168' );
So, what does this mean? The site with the alias @site3 is located in the folder drupal_folder3 on the remote server and has that URI pointing to it on the remote server. This is to be expected. Additionally, you have to specify the remote host (which is the IP address of the remote host). Given that you have set up SSH keys, you will not be required to enter a password unless of course you have a password protecting your private SSH key itself, which I recommend if you are creating keys between two remote hosts (none being your personal computer).
And that's it. Now when you run the commands we've be talking about, you can perform the same actions remotely, as well as migrating and keeping sites synchronized. But just to test out the alias, run:
drush @site3 status
It will take a bit longer than if you are working locally, but it should work nicely.