What are Drush and Capistrano?
At Twinbit we use a customized version of Capistrano (V2) in order to deploy our projects. Furthermore, when the project is based on Drupal we also leverage the power of Drush. Drush is a very useful commandline tool that can operate on different Drupal installations.
The operations that Drush can do are many and varied, and 90% of the time those operations are run at development time against your local Drupal installation, but sometimes it's useful to easily leverage Drush's power on another (remote) installation, be it another dev environment, staging or production.
Drush lets you do this by using the concept of aliases. Simply stated, drush aliases are collection of options for a (possibly remote) Drupal installation; some of these options let you specify how exactly the host should be reached using SSH.
You can get all the information you need regarding aliases running
drush aliases docs-aliases; from there you can see that drush is very customizable, to the point that each option that can be specified on the commandline can be used in an drush alias.
Furthermore drush aliases can be defined at the system level (under
/etc/), at the user level (under
~/.drush/) and at the project level (under
sites/all/drush/ from the main drupal directory) with a complex naming standard that can possibly let you group aliases together.
From my experience it's very usefult to define aliases at the project level so that the entire team can benefit from it.
What problem are we solving?
We had an issue recently with one of our clients having to do with access to machines for deploy purposes.
More precisely we had to be able to access both the staging and production environment, but for security reasons the access was restricted: staging could only be reached via one of our cloud based machines (let's call it bastion from now on) and production could only be reached from staging.
| local development environment |
| bastion |
| staging |
| production |
In this scenario SSH's ProxyCommand option by itself is enough to reach staging, but it never occured to me how to use it to reach production, i.e. when there is one extra host in the middle of the chain.
Drush actually forks a simple ssh process so it's easier to show it first:
$aliases['stage'] = array(
'remote-host' => 'stage_hostname_or_ip',
'remote-user' => 'your_ssh_username_stage',
'ssh-options' => '-o "ProxyCommand ssh -p 9848 [email protected]_hostname_or_ip nc %h %p"',
$aliases['prod1'] = array(
'remote-host' => 'prod1_hostname_or_ip',
'remote-user' => 'your_ssh_username_prod',
'ssh-options' => '-o "ProxyCommand ssh -p 9848 [email protected]_hostname_or_ip nc %h %p" -o ForwardAgent=yes -tt [email protected]_hostname_or_ip ssh -o ForwardAgent=yes -tt',
$aliases['prod2'] = $aliases['prod1'];
$aliases['prod2']['remote-host'] = 'prod2_hostname_or_ip';
I obviously changed ports, usernames, and hostnames/IPs. It's also worth mentioning that a real Drush alias will contain other Drupal specific options like
'uri' => 'http://uri.of.drupal.installation.com',
'root' => '/path/on/filesystem/to/drupal/root',
As you can see our setup was actually more involved in that production was behind a load balancer: so there are actually 2 hosts, and using the setup shown above one can actually run something like
drush @prod1 ssh or
drush @prod2 memcache-storage-clear-cache on a specific host.
For Capistrano (again, V2) the easiest solution I found was to use the
```ruby set :gateway, 'stage_with_proxycommand'
Define an entry in ~/.ssh/config with the following:
ProxyCommand ssh -p 9848 bastion_hostname_or_ip nc %h %p
the following is handy but not required
ssh_options[:forward_agent] = true ```
Using these configurations now it's possible to deploy or execute drush against staging or production from your local development environment, since the proxying through the bastion and, if required, through staging, is performed transparently behind the scenes.