Managing local environments

14 min read

In this article by Juampy Novillo Requena, author of Drush for Developers, Second Edition, we will learn that Drush site aliases offer a useful way to manage local environments without having to be within Drupal’s root directory.

(For more resources related to this topic, see here.)

A site alias consists of an array of settings for Drush to access a Drupal project. They can be defined in different locations, using various file structures. You can find all of its variations at drush topic docs-aliases. In this article, we will use the following variations:

  • We will define local site aliases at $HOME/.drush/aliases.drushrc.php, which are accessible anywhere for our command-line user.
  • We will define a group of site aliases to manage the development and production environments of our sample Drupal project. These will be defined at sites/all/drush/example.aliases.drushrc.php.

In the following example, we will use the site-alias command to generate a site alias definition for our sample Drupal project:

$ cd /home/juampy/projects/example
$ drush --uri=example.local site-alias --alias-name=example.local @self
$aliases["example.local"] = array (
 'root' => '/home/juampy/projects/example',
 'uri' => 'example.local',
 '#name' => 'self',

The preceding command printed an array structure for the $aliases variable. You can see the root and uri options. There is also an internal property called #name that we can ignore. Now, we will place the preceding output at $HOME/.drush/aliases.drushrc.php so that we can invoke Drush commands to our local Drupal project from anywhere in the command-line interface:

* @file
* User-wide site alias definitions.
* Site aliases defined here are available everywhere for the current user.
// Sample Drupal project.
$aliases["example.local"] = array (
'root' => '/home/juampy/projects/example',
'uri' => 'example.local',

Here is how we use this site alias in a command. The following example is running the core-status command for our sample Drupal project:

$ cd /home/juampy
$ drush @example.local core-status
 Drupal version                 : 7.29-dev                               
 Site URI                       : example.local                               
 Database driver                 : mysql                               
 Database username               : root                                   
 Database name                   : drupal7x                               
 Database                       : Connected                               
 Drush alias files              : /home/juampy/.drush/aliases.drushrc.php 
 Drupal root                     : /home/juampy/projects/example           
 Site path                       : sites/default                           
 File directory path             : sites/default/files                     

Drush loaded our site alias file and used the root and uri options defined in it to find and bootstrap Drupal. The preceding command is equivalent to the following one:

$ drush --root=/home/juampy/projects/example 
 --uri=example.local core-status

While $HOME/.drush/aliases.drushrc.php is a good place to define site aliases in your local environment, /etc/drush is a first class directory to place site aliases in servers. Let’s discover now how we can connect to remote environments via Drush.

Managing remote environments

Site aliases that reference remote websites can be accessed by Drush through a password-less SSH connection ( Before we start with these, let’s make sure that we meet the requirements.

Verifying requirements

First, it is recommended to install the same version of Drush in all the servers that host your website. Drush will fail to run a command if it is not installed in the remote machine except for core-rsync, which runs rsync, a non-Drush command that is available in Unix-like systems.

If you can already access the server that hosts your Drupal project through a public key, then skip to the next section. If not, you can either use the pushkey command from Drush extras (, or continue reading to set it up manually.

Accessing a remote server through a public key

The first thing that we need to do is generate a public key for our command-line user in our local machine. Open the command-line interface and execute the following command. We will explain the output step by step:

$ cd $HOME
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/juampy/.ssh/id_rsa):

By default, SSH keys are created at $HOME/.ssh/. It is fine to go ahead with the suggested path in the preceding prompt; so, let’s hit Enter and continue:

Created directory '/home/juampy/.ssh'.
Enter passphrase (empty for no passphrase): *********
Enter same passphrase again: *********

If the .ssh directory does not exist for the current user, the ssh-keygen command will create it with the correct permissions. We are next prompted to enter a passphrase. It is highly recommended to set one as it makes our private key safer. Here is the rest of the output once we have entered a passphrase:

Your identification has been saved in /home/juampy/.ssh/id_rsa.
Your public key has been saved in /home/juampy/.ssh/
The key fingerprint is:
6g:bf:3j:a2:00:03:a6:00:e1:43:56:7a:a0:c7:e9:f3 juampy@juampy-box
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|..               |
|o..*             |
|o + . . S        |
| + * = . .       |
| = O o . .       |
|   *.o * . .     |
|   .oE oo.       |

The result is a new hidden directory under our $HOME path named .ssh. This directory contains a private key file (id_rsa) and a public key file ( The former is to be kept secret by us, while the latter is the one we will copy into remote servers where we want to gain access.

Now that we have a public key, we will announce it to the SSH agent so that it can be used without having to enter the passphrase every time:

$ ssh-add ~/.ssh/id_rsa
Identity added: /home/juampy/.ssh/id_rsa (/home/juampy/.ssh/id_rsa)

Our key is ready to be used. Assuming that we know an SSH username and password to access the server that hosts the development environment of our website, we will now copy our public key into it. In the following command, replace exampledev and with the username and server’s URL of your server:

$ ssh-copy-id's password:
Now try logging into the machine, with "ssh
''", and check
in: ~/.ssh/authorized_keys to make sure we
haven't added extra keys that you weren't

Our public key has been copied to the server and now we do not need to enter a password to identify ourselves anymore when we log in to it. We could have logged on to the server ourselves and manually copied the key, but the benefit of using the ssh-copy-id command is that it takes care of setting the right permissions to the ~/.ssh/authorized_keys file. Let’s test it by logging in to the server:

$ ssh

We are ready to set up remote site aliases and run commands using the credentials that we have just configured. We will do this in the next section.

If you have any trouble setting up SSH authentication, you can find plenty of debugging tips at and

Defining a group of remote site aliases for our project

Before diving into the specifics of how to define a Drush site alias, let’s assume the following scenario: you are part of a development team working on a project that has two environments, each one located in its own server:

  • Development, which holds the bleeding edge version of the project’s codebase. It can be reached at
  • Production, which holds the latest stable release and real data. It can be reached at
  • Additionally, there might be a variable amount of local environments for each developer in their working machines; although, these do not need a site alias.

Given the preceding scenario and assuming that we have SSH access to the development and production servers, we will create a group of site aliases that identify them. We will define this group at sites/all/drush/example.aliases.drushrc.php within our Drupal project:

* @file
* Site alias definitions for Example project.
// Development environment.
$aliases['dev'] = array(
'root' => '/var/www/exampledev/docroot',
'uri' => '',
'remote-host' => '',
'remote-user' => 'exampledev',
// Production environment.
$aliases['prod'] = array(
'root' => '/var/www/exampleprod/docroot',
'uri' => '',
'remote-host' => '',
'remote-user' => 'exampleprod',

The preceding file defines two arrays for the $aliases variable keyed by the environment name. Drush will find this group of site aliases when being invoked from the root of our Drupal project. There are many more settings available, which you can find by reading the contents of the drush topic docs-aliases command.

These site aliases contain options known to us: root and uri refer to the remote root path and the hostname of the remote Drupal project. There are also two new settings: remote-host and remote-uri. The former defines the URL of the server hosting the website, while the latter is the user to authenticate Drush when connecting via SSH.

Now that we have a group of Drush site aliases to work with, the following section will cover some examples using them.

Using site aliases in commands

Site aliases prepend a command name for Drush to bootstrap the site and then run the command there. Our site aliases are and The word example comes from the filename example.aliases.drushrc.php, while dev and prod are the two keys that we added to the $aliases array. Let’s see them in action with a few command examples:

Check the status of the Development environment:

$ cd /home/juampy/projects/example
$ drush status
 Drupal version                 : 7.26                           
 Site URI                       :         
 Database driver                : mysql                           
 Database username              : exampledev                     
 Drush temp directory           : /tmp                           
 Drush alias files              : 
 Drupal root                    : /var/www/exampledev/docroot

The preceding output shows the current status of our development environment. Drush sent the command via SSH to our development environment and rendered back the resulting output. Most Drush commands support site aliases. Let’s see the next example.

Log in to the development environment and copy all the files from the files directory located at the production environment:

$ drush site-ssh
 Welcome to server!
$ cd `drush drupal-directory`
$ drush core-rsync @self:%files
You will destroy data from /var/www/exampledev/docroot/sites/default/files and replace with data from
Do you really want to continue? (y/n): y

Note the use of @self in the preceding command, which is a special Drush site alias that represents the current Drupal project where we are located. We are using @self instead of because we are already logged inside the development environment. Now, we will move on to the next example.

Open a connection with the Development environment’s database:

$ drush sql-cli
Welcome to the MySQL monitor. Commands end with ; or g.
mysql> select database();
| database() |
| exampledev |
1 row in set (0.02 sec)

The preceding command will be identical to the following set of commands:

drush site-ssh
cd /var/www/exampledev
drush sql-cli 

However, Drush is so clever that it opens the connection for us. Isn’t this neat? This is one of the commands I use most frequently. Let’s finish by looking at our last example.

Log in as the administrator user in production:

$ drush user-login
 Created new window in existing browser session.

The preceding command creates a login URL and attempts to open your default browser with it. I love Drush!


In this article, we covered practical examples with site aliases. We started by defining a site alias for our local Drupal project, and then went on to write a group of site aliases to manage remote environments for a hypothetical Drupal project with a development and production site. Before using site aliases for our remote environments, we covered the basics of setting up SSH in order for Drush to connect to these servers and run commands there.

Resources for Article:

Further resources on this subject:


Please enter your comment!
Please enter your name here