Posted about 3 years ago. Visible to the public.

Upgrading from Capistrano 2 to 3

Capistrano 3 is a major rework of the framework and requires several adjustments to your deploy configuration files. The biggest change is that they moved away from their custom DSL and use Rake instead. For connecting with and operating on the servers, they bring a new gem SSHKit which does the heavy lifting. It's SSHKit's DSL that is used anywhere inside the Rake tasks. See #Resources at the bottom for examples.

Step 1: Upgrade guide

For migration from 2 to 3, follow this tutorial: Capistrano 3 Upgrade Guide.

Step 2: More changes

  • Task syntax has changed.

    desc 'Run script' task :script, roles: :app, only: { primary: true } do run "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rails runner 'ScriptRunner.go'" end


    desc 'Run script' task :script do on primary :app do within current_path do with rails_env: fetch(:rails_env, 'production') do execute :bundle, 'exec', "rails runner 'ScriptRunner.go'" end end end end
  • There is no :user setting any more. Set the deploy user directly as an option to the server directive. Also, the roles syntax has become more ruby'esque, and the first server will by default be the primary one:

    server '', user: <user here>, roles: %w(app web db)
  • The organization of Capistrano files has changed. It seems the deploy.rb and deploy/*.rb files are only meant for configuration, i.e. many calls to set :<variable>, <value>. Custom tasks should live in lib/capistrano/tasks/*.rake.

  • The deploy:restart task is not automatically run any more! If you need it to run, add an after hook:

    after 'deploy:published', 'deploy:restart'
  • To run code on the servers, you need to use execute instead of run. Caution: When a command passed to execute contains white space, it is run in the home directory instead of the directory you might have specified with within(...) do. I would call that a bug, but the core team disagrees. Basically, execute and capture commands behave like Ruby's system etc. methods. Just call them with separate arguments, e.g. execute :dumple, '--fail-gently'.

  • Hooks have changed:

    deploy:update_code -> deploy:updating
  • Invocation of other tasks has changed:

    # old: namespace.task # new: invoke 'namespace:task'
  • shared/system is now shared/public/system! See this card. This is already handled for our own projects.

Configuration that is not needed any more

set :copy_exclude, ['.git']
The .git repository is excluded from the current directory on the server, but its contents live in the repo directory on the server.
set :allow_sudo, false
Capistrano does no sudo any more.
requiring capistrano/rvm or similar

Error messages

When trying to deploy with Capistrano 3 using your old Capistrano 2 config files, you'll get many error messages that are giving no hint about what really is wrong. The solution to most of them is to strictly hold to the new task syntax.

undefined method `instance' for Capistrano::Configuration:Class
undefined local variable or method `ssh_options' for main:Object
Use the new syntax instead:
set :ssh_options, { ... }
wrong number of arguments (1 for 2)
undefined method `tail' for nil:NilClass
You need to wrap your task body in a on ... do ... end block, e.g.
task :dump do on primary roles :db do # <-- this # perform dump end end
undefined method `map' for :roles:Symbol
You're still using the old task ..., roles: ... syntax, which is not supported any more. Capistrano tasks are Rake tasks now, so you need to specify the roles as shown above (on roles(...) do ... end).
Don't know how to build task 'deploy:update_code'/'deploy:setup'/etc
These error messages may originate from before/after hooks. The Capistrano hooks and deploy tasks have change significantly. See the docs for what to hook on.
SSHKit::Runner::ExecuteError: Exception while executing on host #: getaddrinfo: Name or service not known
You missed the "server fetcher". Syntax example:
on (roles|primary|release_roles|...) :some_role do


Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Author of this card:

Dominik Schöler
Last edit:
6 months ago
by Dominik Schöler
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Dominik Schöler to makandra dev