Drush: Setting up and Leveraging Site Aliases

If you haven't yet set up site aliases for Drush, what are you waiting for?!?--Life is so much easier once your localhost can start communicating with your remote: bring site files and databases straight from production to local without logging into your CPanel or PHPMyAdmin; clear site cache on Production without logging into the site and navigating the admin UI. It can be tricky to set up, but once you have, you'll wonder how you ever developed without site aliases.

Background: Why Site Aliases Rock

My main client is hosted on Acquia; despite the tendency to be both pedantic and overly optimistic in regards to all things Drupal, Acquia, as a company, can be extremely considerate to the developers on its platform. One of the perks of being with Acquia is having out-of-the-box support for Drush Site Aliases. Namely, that means that in order to get Aliases up and going, all you need to do is download a preconfigured YML file and you're pretty much good to go (still need to fill the file in for local, though).

Cool... but, what about anyone not on Acquia?

Outside of Acquia, getting Drush Site Aliases up and running isn't always a simple task. Don't despair, though!--I'm here to help you out. Here's a quick walk through of how to set up Drush Aliases for simple Drupal Site like this very blog. It may take you some time to work out the kinks, but the rewards are well worth it.

What are Site Aliases?

You might think of them as ssh credentials for each environment in your workflow. The aliases can be quite simple, expressing typical ssh data like URI and username; or, they can be quite complicated, specifying things like the path to your site files and options for the ssh connection. In either case, a Site Alias is exactly as its name says: an alias by which Drush can identify and connect to the different sites in your workflow. This is what allows you to target operations in one environment (i.e., clearing cache on PROD) from an entirely different environment (i.e., LOCAL); it also means that you can dump a database from a remote environment and import it into your local DB without leaving your terminal; you can even use aliases for copying site files between one environment and the next.

Requirements

Here are a few quick notes on what you'll need before you get started:

  • Have a valid sitename.site.yml file at drupalroot/drush/sites/sitename.site.yml
    • I'll outline the contents of this file later in this article; you can also refer to my exmple file on GitHub.
    • The sitename key in this filename is something you'll want to take note of; this will be used in the actual aliases for your environments: i.e., @sitename.local @sitename.prod
    • If using Git, you can commit this file to your repository. If, however, you use more than one computer for local development you may want to add the file to your .gitignore--allowing you to configure the file differently for each of your computers.
  • Have the same version of Drush installed on both local and remote
    • I recommend Drush 10+; Drush 9.x has shown bugs with decompressing sql.gz archives--there are workarounds for this but the best workaround is to simply use the most recent version of Drush.
    • If you're installing Drush on a remote, be sure to add Drush to $PATH on the remote. These days, I believe we should all be including Drush as a project dependency. This should be done by running composer require drush/drush -- which should install Drush locally to your project, usually under the drupalroot/vendors  directory. There's some debate over whether the vendors directory should be tracked in the project repository; if you haven't added the directory to .gitignore, you should see consistency in Drush versions regardless of which environment your code runs on. To add Drush to your remote's $PATH, you would likely put something like this in your remote hosts .bashrc file (usually found at /): PATH=$PATH:$HOME/public_html/drupalroot/vendor/drush/drush
      export PATH
    • Don't forget to run $ source .bashrc once you save your remote host's .bashrc file.
    • You should be able to confirm whether Drush was successfully added to your remote's $PATH by running the following on your remote: $ echo $PATH

Setting Up Your YML File

The contents of your YML file are pretty straightforward. Again, this file should be located at the following path: drupalroot/drush/sites/sitename.site.yml

The file will list the various environments within your workflow. Since the site in my example has only two environments (local and production) my file is pretty simple. If you're working with more environments feel free to add an entry for each one. Let's have a look at my example file:

# File: example.site.yml

# Application 'example', enironment 'local'.
local:
  # path to your local drupal root:
  root: /var/www/example
  # some local uri (i.e., what you have in /etc/hosts for your local site):
  uri: localuri
  # 'user' is whatever user apache runs as--but adjust according to however your localhost is setup
  user: www-data
  # (optional) declare path to your local site files:
  # Drush should gather this path by default, but I needed to declare it for my local
  paths: 
   - files: /var/www/example/sites/default/files

# Application 'example', enironment 'prod'. 
prod: 
  # host name (can be same as uri):
  host: remoteuri.com
  # remore user name (i.e., user name used when logging in via ssh):
  user: remoteuser
  # remote drupal root: 
  root: /home/remoteuser/public_html/example 
  # remote uri: 
  uri: remoteuri.com
  # (optional) path to site files on remote:
  paths:
   - files: /home/remoteuser/public_html/example/sites/default/files

The trick here is to understand that each environment key will become part of your alias. Here, my site name is 'example' (Drush will gather this site name from the file's name--example.site.yml), and my environment keys are 'local' and 'prod' respectively. My site aliases would then be: @example.local and @example.prod. You can verify your aliases, and whether this file has been put together correctly, by simply running $ drush sa from within your project folder. If the file isn't formatted correctly I imagine you won't get any output.

Once your aliases are in place you can begin testing whether the aliases actually work. Let's look at a few commands you might use:

Drush: Clearing Cache on Remote

This is a simple task, but you can certainly use it to make sure Drush is actually able to log into your remote. On your command line, you can run $ drush @example.prod cr (use, of course, your own site alias for production). If it doesn't work, you may need to double check that the SSH credentials in your YML file are correct. Another reason this might not work is because you haven't added Drush to your remote $PATH. It IS possible to not have Drush in your remote $PATH and still be able to use Drush on your remote. Be sure that you have added Drush to your remote's $PATH. This command, clearing a cache on remote, might be something you want to create a Bash alias for. I run a script locally that will allow me to target multiple remotes for cache rebuild with just a few keystrokes.

Drush: Copying a Database from PROD to LOCAL

Once you're sure Drush can log in and run commands on your remote environment, you might then try passing data from there to your local host. You might test this by bringing down one of your production databases. The syntax for this should look something like this: $ drush sql:drop && drush sql:sync @example.prod @example.local NOTE: be careful not to mix up [SOURCE] and [TARGET] aliases; the source will be the first alias, the target will be the second. Drush should provide a few sanity checks before it actually drops your local DB and brings in the DB from production. This is also a command you might want to throw into a Bash alias.

Here, there are a few hiccups you might want to be on the lookout for. Again, per my comments in the 'Requirements' section, you'll want to be sure that Drush has support for whatever file-type your dump file gets archived as. My dump files were coming off production as .gz files; Drush 9.x needed a quick fix in the config file to make sure that .gz files could even be unarchived. If this is a fresh LAMP stack you're setting up alongside your Drush site aliases, you'll want to be sure that Drush is actually able to connect to your Database. If you run into any MYSQL errors you'll want to try debugging with bare MYSQL commands (i.e., be sure you can drop and import with MYSQL on the command line without Drush). Errors here may indicate a problem with your MYSQL setup.

Let's have a look at one more useful command using site aliases.

Drush: Copying Files from PROD to LOCAL

Bringing in files without the use of an FTP client is such a godsend! Once again, it's a pretty straightforward affair: run $ drush rsync @example.prod:%files @example.local:%files and you're good to go. As with bringing in a DB, you'll want to be careful to use [SOURCE] and [TARGET] correctly here--although, rsync should only ever bring in changes between one environment and the other (i.e., what's newer). In my case, I could initially only get this to work by specifying the exact path to my local files directory--i.e., $ drush rsync @example.prod:%files /path/to/files. Drush should be able to find the path to your files without any help, but this is why I've included paths to the files directories for both local and remote in my YML example. Play around: see what works best for you. It's also nice to know that you can specify alternative destination paths.

Trouble Shooting

Drush can rely heavily on command line tools. It behaves as a middle man of sorts (sending requests to other programs and delivering the results). Rsync, for example, is a tool you can run without Drush; MYSQL also needs to be running smoothly independent of Drush. When you get turned around with Drush, a good strategy is to make sure that you can perform the tasks Drush is looking to perform without the use of Drush. If you're having trouble running the bare command, you'll have trouble with Drush as well. This is perhaps the biggest hurdle to leveraging Drush correctly: in order to do it efficiently, you need to have a decent grasp of the tools Drush relies on. Remember to use the -vvv option for Drush debugging. It can provide good info.