What is Capistrano?

Capistrano is a remote server automation tool.

It supports the scripting and execution of arbitrary tasks, and includes a set of sane-default deployment workflows.

Capistrano can be used to:

  • Reliably deploy web application to any number of machines simultaneously, in sequence or as a rolling set
  • To automate audits of any number of machines (checking login logs, enumerating uptimes, and/or applying security patches)
  • To script arbitrary workflows over SSH
  • To automate common tasks in software teams.
  • To drive infrastructure provisioning tools such as chef-solo, Ansible or similar.

Capistrano is also very scriptable, and can be integrated with any other Ruby software to form part of a larger tool.

What does it look like?

Capistrano 3.5 / Airbrussh formatter screenshot

What else is in the box?

There’s lots of cool stuff in the Capistrano toy box:

  • Interchangeable output formatters (progress, pretty, html, etc)
  • Easy to add support for other source control management software.
  • A rudimentary multi-console for running Capistrano interactively.
  • Host and Role filters for partial deploys, or partial-cluster maintenance.
  • Recipes for the Rails asset pipelines, and database migrations.
  • Support for complex environments.
  • A sane, expressive API:
desc "Show off the API"
task :ditty do

  on roles(:all) do |host|
    # Capture output from the remote host, and re-use it
    # we can reflect on the `host` object passed to the block
    # and use the `info` logger method to benefit from the
    # output formatter that is selected.
    uptime = capture('uptime')
    if host.roles.include?(:web)
      info "Your webserver #{host} has uptime: #{uptime}"

  on roles(:app) do
    # We can set environmental variables for the duration of a block
    # and move the process into a directoy, executing arbitrary tasks
    # such as letting Rails do some heavy lifting.
    with({:rails_env => :production}) do
      within('/var/www/my/rails/app') do
        execute :rails, :runner, 'MyModel.something'

  on roles(:db) do
    # We can even switch users, provided we have support on the remote
    # server for switching to that user without being prompted for a
    # passphrase.
    as 'postgres' do
      widgets = capture "echo 'SELECT * FROM widgets;' | psql my_database"
      if widgets.to_i < 50
        warn "There are fewer than 50 widgets in the database on #{host}!"

  on roles(:all) do
    # We can even use `test` the way the Unix gods intended
    if test("[ -d /some/directory ]")
      info "Phew, it's ok, the directory exists!"
Fork me on GitHub