--- title: What is Capistrano? layout: default --- ### Capistrano is a remote server automation tool. It supports the scripting and execution of arbitrary tasks, and includes a set of sane-default deployment workdflows. Capistrano can be used to: * Reliably deploy web application to any number of machines simultaniously, 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 too. #### What does it look like? {% prism bash %} me@localhost $ cap staging deploy {% endprism %}
DEBUG Uploading /tmp/git-ssh.sh 0%
 INFO Uploading /tmp/git-ssh.sh 100%
 INFO [649ae05d] Running /usr/bin/env chmod +x /tmp/git-ssh.sh on example.com
DEBUG [649ae05d] Command: /usr/bin/env chmod +x /tmp/git-ssh.sh
 INFO [649ae05d] Finished in 0.048 seconds command successful.
 INFO [6a86a816] Running /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git on example.com
DEBUG [6a86a816] Command: ( GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/git-ssh.sh /usr/bin/env git ls-remote git@github.com:capistrano/rails3-bootstrap-devise-cancan.git )
DEBUG [6a86a816]     3419812c9f146d9a84b44bcc2c3caef94da54758	HEAD
DEBUG [6a86a816]     3419812c9f146d9a84b44bcc2c3caef94da54758	refs/heads/master
 INFO [6a86a816] Finished in 2.526 seconds command successful.
 INFO [26c22cce] Running /usr/bin/env mkdir -pv /var/www/my-application/shared /var/www/my-application/releases on example.com
DEBUG [26c22cce] Command: /usr/bin/env mkdir -pv /var/www/my-application/shared /var/www/my-application/releases
 INFO [26c22cce] Finished in 0.439 seconds command successful.
DEBUG [682cbb14] Running /usr/bin/env [ -f /var/www/my-application/repo/HEAD ] on example.com
DEBUG [682cbb14] Command: [ -f /var/www/my-application/repo/HEAD ]
DEBUG [682cbb14] Finished in 0.448 seconds command failed.
DEBUG [902d6fe6] Running /usr/bin/env if test ! -d /var/www/my-application; then echo "Directory does not exist '/var/www/my-application'" 1>&2; false; fi on example.com
DEBUG [902d6fe6] Command: if test ! -d /var/www/my-application; then echo "Directory does not exist '/var/www/my-application'" 1>&2; false; fi
DEBUG [902d6fe6] Finished in 0.047 seconds command successful.
 INFO [70365162] Running /usr/bin/env git clone --mirror git@github.com:capistrano/rails3-bootstrap-devise-cancan.git /var/www/my-application/repo on example.com
DEBUG [70365162] Command: cd /var/www/my-application && ( GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/git-ssh.sh /usr/bin/env git clone --mirror git@github.com:capistrano/rails3-bootstrap-devise-cancan.git /var/www/my-application/repo )
DEBUG [70365162]     Cloning into bare repository '/var/www/my-application/repo'...
DEBUG [70365162]     remote: Counting objects: 598, done.
 INFO [70365162] Finished in 3.053 seconds command successful.
DEBUG [4d3ef555] Running /usr/bin/env if test ! -d /var/www/my-application/repo; then echo "Directory does not exist '/var/www/my-application/repo'" 1>&2; false; fi on example.com
DEBUG [4d3ef555] Command: if test ! -d /var/www/my-application/repo; then echo "Directory does not exist '/var/www/my-application/repo'" 1>&2; false; fi
DEBUG [4d3ef555] Finished in 0.445 seconds command successful.
 INFO [90a42e63] Running /usr/bin/env git remote update on example.com
DEBUG [90a42e63] Command: cd /var/www/my-application/repo && /usr/bin/env git remote update
DEBUG [90a42e63] 	Fetching origin
 INFO [90a42e63] Finished in 2.078 seconds command successful.
DEBUG [39a7244f] Running /usr/bin/env if test ! -d /var/www/my-application/repo; then echo "Directory does not exist '/var/www/my-application/repo'" 1>&2; false; fi on example.com
DEBUG [39a7244f] Command: if test ! -d /var/www/my-application/repo; then echo "Directory does not exist '/var/www/my-application/repo'" 1>&2; false; fi
DEBUG [39a7244f] Finished in 0.455 seconds command successful.
 INFO [8665f0f1] Running /usr/bin/env git clone --branch master --depth 1 --recursive --no-hardlinks /var/www/my-application/repo /var/www/my-application/releases/20130625064744 on example.com
DEBUG [8665f0f1] Command: cd /var/www/my-application/repo && ( GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/git-ssh.sh /usr/bin/env git clone --branch master --depth 1 --recursive --no-hardlinks /var/www/my-application/repo /var/www/my-application/releases/20130625064744 )
DEBUG [8665f0f1]     warning: --depth is ignored in local clones; use file:// instead.
DEBUG [8665f0f1]     Cloning into '/var/www/my-application/releases/20130625064744'...
DEBUG [8665f0f1]     done.
 INFO [8665f0f1] Finished in 0.141 seconds command successful.
 INFO [bfd2d6bd] Running /usr/bin/env rm -rf /var/www/my-application/current on example.com
DEBUG [bfd2d6bd] Command: /usr/bin/env rm -rf /var/www/my-application/current
 INFO [bfd2d6bd] Finished in 0.474 seconds command successful.
 INFO [54ea9e57] Running /usr/bin/env ln -s /var/www/my-application/releases/20130625064744 /var/www/my-application/current on example.com
DEBUG [54ea9e57] Command: /usr/bin/env ln -s /var/www/my-application/releases/20130625064744 /var/www/my-application/current
 INFO [54ea9e57] Finished in 0.054 seconds command successful.
DEBUG [b5af33fb] Running /usr/bin/env ls -xt /var/www/my-application/releases on example.com
DEBUG [b5af33fb] Command: /usr/bin/env ls -xt /var/www/my-application/releases
DEBUG [b5af33fb]     20130625064744
DEBUG [b5af33fb] Finished in 0.445 seconds command successful.
DEBUG [10b6e05d] Running /usr/bin/env if test ! -d /var/www/my-application/releases; then echo "Directory does not exist '/var/www/my-application/releases'" 1>&2; false; fi on example.com
DEBUG [10b6e05d] Command: if test ! -d /var/www/my-application/releases; then echo "Directory does not exist '/var/www/my-application/releases'" 1>&2; false; fi
DEBUG [10b6e05d] Finished in 0.452 seconds command successful.
 INFO [dd6ef5b4] Running /usr/bin/env echo "Branch master deployed as release 20130625064744 by leehambley; " >> /var/www/my-application/revisions.log on example.com
DEBUG [dd6ef5b4] Command: echo "Branch master deployed as release 20130625064744 by leehambley; " >> /var/www/my-application/revisions.log
 INFO [dd6ef5b4] Finished in 0.046 seconds command successful.
#### What else is in the box? There's lots of cool stuff in the Capistrano toy box: * Interchangable 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: {% prism ruby %} 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}" end end on roles(:app) do # We can set environmental varaibles 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' end end end 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}!" end end end 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!" end end end {% endprism %}