Capistrano is great for remote server automation over SSH but often I find myself only needing small parts from what the full
Capistrano suite has to offer. Starting with Capistrano 3, the SSH-part of Capistrano was split out into a separate project called
SSHKit .
SSHKit comes with a neat DSL that we can easily embed in our Rakefiles. Lets go through an example of how I deploy my Jekyll-powered blog via Rake:
# Rakefile
require 'yaml'
require 'sshkit'
require 'sshkit/dsl'
config = YAML . load_file ( '_config.yml' )
deploy_server = config [ 'deploy_server' ]
deploy_path = config [ 'deploy_path' ]
deploy_user = config [ 'deploy_user' ]
SSHKit :: Backend :: Netssh . configure do | ssh |
ssh . ssh_options = {
user: deploy_user ,
auth_methods: [ 'publickey' ]
}
end
desc 'Deploy the site to production'
task :deploy do
run_locally do
execute 'jekyll' , 'build'
end
on deploy_server do
unless test "[ -d #{ deploy_path } ]"
as :root do
execute 'mkdir' , '-p' , deploy_path
end
end
unless test "[ `stat -c %U #{ deploy_path } ` = ' #{ deploy_user } ']"
as :root do
execute 'chown' , '-R' , deploy_user , deploy_path
end
end
upload! "_site/" , deploy_path , recursive: true
end
end
The desc
and task
are just plain Rake keywords. The rest of the DSL is SSHKit. Lets clean the code up and extract a Blog
class:
# Rakefile
require 'yaml'
require 'sshkit'
require 'sshkit/dsl'
config = YAML . load_file ( '_config.yml' )
deploy_server = config [ 'deploy_server' ]
deploy_path = config [ 'deploy_path' ]
deploy_user = config [ 'deploy_user' ]
SSHKit :: Backend :: Netssh . configure do | ssh |
ssh . ssh_options = {
user: deploy_user ,
auth_methods: [ 'publickey' ]
}
end
class Blog
def initialize ( host , path , owner )
@host = host
@path = path
@owner = owner
end
def deploy!
compile
upload
end
private
def upload
with_deploy_location_ready do
@host . upload! "_site/" , @path , recursive: true
end
end
def with_deploy_location_ready
create_deploy_path unless deploy_path_exists?
chown_to_owner unless deploy_path_owned?
yield
end
def deploy_path_exists?
@host . test "[ -d #{ @path } ]"
end
def create_deploy_path
@host . as :root do
@host . execute 'mkdir' , '-p' , @path
end
end
def deploy_path_owned?
@host . test "[ `stat -c %U #{ @path } ` = ' #{ @owner } ']"
end
def chown_to_owner
@host . as :root do
@host . execute 'chown' , '-R' , @owner , @path
end
end
def compile
@host . run_locally { execute 'jekyll' , 'build' }
end
end
desc 'Deploy the site to production'
task :deploy do
on deploy_server do
Blog . new ( self , deploy_path , deploy_user ). deploy!
end
end
That’s pretty neat I think! For more documentation of SSHKit, have a look at its EXAMPLES .