On a recent project, I had a need to deploy over 100 copies of the same repository with different settings for each. Since Capistrano wasn’t exactly built for this type of deployment, I had to get creative. This method will separate each site into a stage, built from a template that pulls information from a YAML file for the desired environment. This allows individual testing for each site, as well as deployment across all sites, and eliminates problems with variable scope while writing tasks.
Setting the stage
The first step is to build site specific parameters in environment YAML files, which can be easily updated with new sites or configuration changes. We’ll store these files in lib/deploy/. All passwords should be encrypted for security purposes and decrypted in the configuration phase. The YAML file will consist of a nested hash for each site’s configuration values:
Our config/deploy.rb file will have the following values to load the YAML docs and get us setup to deploy.
Building the stages
Without writing some ruby, the only way I’ve found to effectively build individual parameters for each site is to create config files for each and loop through them locally. Overwriting global values in capistrano for each site while performing each task needed can run into problems with scope that are more easily solved with separate stages.
First we need to write a template class to build the stages from an ERB template.
The template file will include all of the variables we’ll be accessing for the deployment. Name these for your environments in lib/capistrano/templates, such as lib/capistrano/templates/devel.rb.erb.
Next we use this template to build the staging configuration files, stored in config/deploy/. They’ll be named application_stage and we’ll configure this to run before the task we’ll write to loop through all of the sites in our YAML document.
Deploying the sites
Now all of these stages can be accessed individually, which makes testing much easier. We just need a task that will deploy them all in a single command, which has to be run locally on either your workstation or the CI/CD tool of your choice.
All that’s left is to run