capistrano-ssh-doctor 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7f6a315084d957611956b98eb45770af4d663d31
4
+ data.tar.gz: 2ed9041723f8508c57e4e54d2166fee521d67dc9
5
+ SHA512:
6
+ metadata.gz: 736cb8e50188ecd0dc1144a7cd0d3624e5adbfd878623ad2f725ab3d7154aec681b6cfc19bda5d53154f098dc663743b8ba225d79c4bcc9a168bf3ab4d42774d
7
+ data.tar.gz: 67a494421f56b50a120a3527d9af164d9e40cdc37cf3f4f212ece7203705ffdf480a4fde641c19a07d286f787136fd3a3fd9820b374d6d0663126d583ebfc8ef
File without changes
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2014 Bruno Sutic
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included
11
+ in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
19
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,116 @@
1
+ # Capistrano SSH Doctor
2
+
3
+ This plugin helps you setup and debug `ssh-agent` forwarding for Capistrano
4
+ deployment.
5
+
6
+ It's created to complement the official [capistrano authentication guide](http://capistranorb.com/documentation/getting-started/authentication-and-authorisation/).
7
+
8
+ The following is presumed:
9
+ - you're using `git`
10
+ - you want to use passwordless ssh login to the servers
11
+ - you want to use the `ssh-agent` forwarding strategy for checking out code in
12
+ the remote repository (btw. good choice, it's a least hassle)
13
+
14
+ The plugin will report errors (and offer steps to solution) if you deviate from
15
+ this configuration. The above assumptions should hold true for 98% users.
16
+
17
+ `capistrano-ssh-doctor` works only with Capistrano **3+**.
18
+
19
+ ### Who should use it?
20
+
21
+ The plugin is made for beginners and users that are not sure if their setup is
22
+ good, so they want to confirm or debug it.
23
+
24
+ If you have enough knowldge/experience with `ssh` tool and you're sure you have
25
+ `ssh-agent` forwarding working for your server, you probably don't need this
26
+ plugin.
27
+
28
+ ### Installation
29
+
30
+ Put the following in your application's `Gemfile`:
31
+
32
+ group :development do
33
+ gem 'capistrano', '~> 3.1'
34
+ gem 'capistrano-ssh-doctor'
35
+ end
36
+
37
+ Then run in the console:
38
+
39
+ $ bundle install
40
+
41
+ Put the following in `Capfile` file:
42
+
43
+ require 'capistrano/ssh_doctor'
44
+
45
+ ### Usage
46
+
47
+ This plugin is intended to be used **before** any deployment task.
48
+
49
+ In the console run:
50
+
51
+ $ bundle exec cap production ssh:doctor
52
+
53
+ The plugin will perform a number of checks and output a report at the end.
54
+
55
+ **Solving Errors**
56
+
57
+ In case there are errors in your setup, specific instructions for next
58
+ steps will be provided in report output.
59
+
60
+ **Important:** errors should be tackled in the order of their output. So, if
61
+ you got errors 2, 5 and 7 in the report, start by solving error 2.
62
+
63
+ It is very probable that "solving" one or two initial errors will actually make
64
+ everything work. A lot of the checks are inter-dependent. So don't be
65
+ discouraged if you see a lot of the errors in the beginning.
66
+
67
+ Once you solved a problem, run the `ssh:doctor` task again to see the
68
+ progress.
69
+
70
+ Repeat the process until `ssh:doctor` task reports success for all the
71
+ tasks. You're ok with proceeding with the deployment then.
72
+
73
+ ### Which checks are performed?
74
+
75
+ 1. checks that you're using `git` repository protocol
76
+ 2. checks that ssh private key file exists locally
77
+ 3. checks if `ssh-agent` process is running locally
78
+ 4. checks that `ssh-add` process can communicate with `ssh-agent`
79
+ 5. checks that ssh private keys are loaded to `ssh-agent`
80
+ 6. checks that remote code repository is accessible from local machine
81
+ 7. checks passwordless ssh login is used for all servers
82
+ 8. checks `forward_agent` capistrano option is set to `true` for all servers
83
+ 9. checks `ssh-agent` is actually forwared to all the servers
84
+ 10. checks remote code repository is accessible from all the servers
85
+
86
+ You'll see the results for all the checks in the output of `ssh:doctor`
87
+ task.
88
+
89
+ ### More Capistrano automation?
90
+
91
+ If you'd like to streamline your Capistrano deploys, you might want to check
92
+ these zero-configuration, plug-n-play plugins:
93
+
94
+ - [capistrano-unicorn-nginx](https://github.com/bruno-/capistrano-unicorn-nginx)<br/>
95
+ no-configuration unicorn and nginx setup with sensible defaults
96
+ - [capistrano-postgresql](https://github.com/bruno-/capistrano-postgresql)<br/>
97
+ plugin that automates postgresql configuration and setup
98
+ - [capistrano-rbenv-install](https://github.com/bruno-/capistrano-rbenv-install)<br/>
99
+ would you like Capistrano to install rubies for you automatically?
100
+ - [capistrano-safe-deploy-to](https://github.com/bruno-/capistrano-safe-deploy-to)<br/>
101
+ if you're annoyed that Capistrano does **not** create a deployment path for the
102
+ app on the server (default `/var/www/myapp`), this is what you need!
103
+
104
+ ### Contributing and bug reports
105
+
106
+ If you got stuck at some point and really can't find a solution, please open a
107
+ [github issue](/issues) and maybe I can help you.
108
+
109
+ Also, I can use your problem to improve this plugin.
110
+
111
+ ### License
112
+
113
+ [MIT](LICENSE.md)
114
+
115
+ # TODO
116
+ - do not store text in report hash, store only success/fail there
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'capistrano/ssh_doctor/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'capistrano-ssh-doctor'
8
+ gem.version = Capistrano::SshDoctor::VERSION
9
+ gem.authors = ['Bruno Sutic']
10
+ gem.email = ['bruno.sutic@gmail.com']
11
+ gem.description = <<-EOF.gsub(/^\s+/, '')
12
+ This plugin helps you setup and debug `ssh-doctor` forwarding for Capistrano
13
+ deployment.
14
+
15
+ It peforms a number of checks on the local machine as well as on the
16
+ servers. Report output with suggested next steps is provided in case there
17
+ are any errors with the setup.
18
+ EOF
19
+ gem.summary = 'This plugin helps you setup and debug `ssh-doctor` forwarding for Capistrano deployment.'
20
+ gem.homepage = 'https://github.com/bruno-/capistrano-ssh-doctor'
21
+
22
+ gem.license = 'MIT'
23
+
24
+ gem.files = `git ls-files`.split($/)
25
+ gem.require_paths = ['lib']
26
+
27
+ gem.add_dependency 'capistrano', '>= 3.1'
28
+
29
+ gem.add_development_dependency 'rake'
30
+ end
File without changes
@@ -0,0 +1 @@
1
+ load File.expand_path('../tasks/ssh_doctor.rake', __FILE__)
@@ -0,0 +1,14 @@
1
+ require_relative 'report'
2
+
3
+ module Capistrano
4
+ module SshDoctor
5
+ module DSL
6
+
7
+ def report
8
+ Capistrano::SshDoctor::Report.report
9
+ end
10
+
11
+ end
12
+ end
13
+ end
14
+ self.extend Capistrano::SshDoctor::DSL
@@ -0,0 +1,67 @@
1
+ require_relative 'report/messages'
2
+
3
+ module Capistrano
4
+ module SshDoctor
5
+ class Report
6
+
7
+ include Capistrano::SshDoctor::Report::Messages
8
+
9
+ def self.report
10
+ @report ||= new
11
+ end
12
+
13
+ def initialize
14
+ @report_messages = default_messages
15
+ end
16
+
17
+ def report_error_for(key, hosts=nil)
18
+ error_message = send(key + "_error", hosts)
19
+ set_error(key.to_sym, error_message)
20
+ end
21
+
22
+ def print
23
+ print_header
24
+ @report_messages.each_with_index do |(key, message), index|
25
+ print_message(index + 1, message)
26
+ end
27
+ print_footer
28
+ end
29
+
30
+ private
31
+
32
+ def set_error(key, message)
33
+ @report_messages[key] = [ :error, message ]
34
+ end
35
+
36
+ def has_errors?
37
+ @report_messages.any? {|key, value| value[0] == :error }
38
+ end
39
+
40
+ def print_header
41
+ puts
42
+ puts "SSH agent forwarding report"
43
+ puts "---------------------------"
44
+ puts
45
+ end
46
+
47
+ def print_message(index, message)
48
+ puts "#{index}. [#{message[0]}] #{message[1]}"
49
+ puts
50
+ end
51
+
52
+ def print_footer
53
+ puts "----------------------"
54
+ puts
55
+ if has_errors?
56
+ puts "It seems SSH agent forwarding is not set up correctly."
57
+ puts "Follow the suggested steps described in error messages."
58
+ puts "Errors (if more than one) are ordered by importance, so always start with the first one."
59
+ else
60
+ puts "It seems SSH agent forwarding is set up correctly!"
61
+ puts "You can continue with the deployment process."
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,168 @@
1
+ module Capistrano
2
+ module SshDoctor
3
+ class Report
4
+ module Messages
5
+
6
+ def default_messages
7
+ {
8
+ config_repo_url: [
9
+ :success, '`repo_url` setting ok'
10
+ ],
11
+ local_private_key_exists: [
12
+ :success, 'ssh private key file exists'
13
+ ],
14
+ local_agent_running_env_var: [
15
+ :success, '`ssh-agent` process seems to be running locally'
16
+ ],
17
+ local_agent_running_ssh_add: [
18
+ :success, '`ssh-agent` process recognized by `ssh-add` command'
19
+ ],
20
+ local_keys_added_to_agent: [
21
+ :success, 'ssh private keys added to `ssh-agent`'
22
+ ],
23
+ local_repo_access: [
24
+ :success, 'application repository accessible from local machine'
25
+ ],
26
+ config_password: [
27
+ :success, 'all hosts using passwordless login'
28
+ ],
29
+ config_agent_forwarding: [
30
+ :success, '`forward_agent` ok for all hosts'
31
+ ],
32
+ remote_agent_running: [
33
+ :success, 'ssh agent successfully forwarded to remote hosts'
34
+ ],
35
+ remote_repo_access: [
36
+ :success, 'application repository accessible from remote hosts'
37
+ ]
38
+ }
39
+ end
40
+
41
+ def config_repo_url_error(_)
42
+ <<-EOF.gsub(/^\s+/, '')
43
+ It seems the git repository url in `repo_url` setting uses https
44
+ protocol. Https protocol prompts for password and so git protocol
45
+ should be used.
46
+
47
+ Actions:
48
+ - change `repo_url` setting in `config/deploy.rb` file to use git protocol.
49
+ Example for github: `git@github.com:username/repo.git`
50
+ EOF
51
+ end
52
+
53
+ def config_password_error(hosts)
54
+ msg = "It seems Capistrano connects to the following hosts using password login:\n"
55
+ msg << hosts.map(&:to_s).join(', ')
56
+ msg.concat "\n"
57
+ msg.concat <<-EOF.gsub(/^\s+/, '')
58
+ It is strongly suggested to use passwordless ssh login.
59
+
60
+ Actions:
61
+ - make sure you're *not* using password to connect to any of the servers.
62
+ - remove any password setting from `ssh_options` in Capistrano stage files
63
+ (e.g. `config/deploy/production.rb`).
64
+ By removing password configuration - the default, passwordless ssh
65
+ connection will be used.
66
+ - setup passwordless ssh connection for your servers
67
+ http://askubuntu.com/questions/4830/easiest-way-to-copy-ssh-keys-to-another-machine/4833#4833
68
+ EOF
69
+ end
70
+
71
+ def config_agent_forwarding_error(hosts)
72
+ msg = "It seems Capistrano connects without ssh agent forwarding to the following hosts:\n"
73
+ msg << hosts.join(', ')
74
+ msg.concat "\n"
75
+ msg.concat <<-EOF.gsub(/^\s+/, '')
76
+ Actions:
77
+ - make sure Capistrano uses the default ssh option for `forward_agent`.
78
+ Just remove any `forward_agent` setting from the stage file (e.g.
79
+ `config/deploy/production.rb`) and the default, `true` value will be used.
80
+ EOF
81
+ end
82
+
83
+ def local_private_key_exists_error(_)
84
+ <<-EOF.gsub(/^\s+/, '')
85
+ Uh, oh. It seems you do not have ssh private keys generated, or they're
86
+ not located in standard location.
87
+
88
+ Actions:
89
+ - here's a good guide how to generate ssh private keys and set them
90
+ up with github
91
+ https://help.github.com/articles/generating-ssh-keys
92
+ EOF
93
+ end
94
+
95
+ def local_agent_running_env_var_error(_)
96
+ <<-EOF.gsub(/^\s+/, '')
97
+ It seems `ssh-agent` is not running on local machine.
98
+
99
+ Actions:
100
+ - follow this guide
101
+ http://mah.everybody.org/docs/ssh
102
+ EOF
103
+ end
104
+
105
+ def local_agent_running_ssh_add_error(_)
106
+ <<-EOF.gsub(/^\s+/, '')
107
+ It seems ssh-add cannot make a connection with ssh-agent process
108
+ on local machine.
109
+
110
+ Actions:
111
+ - are you sure all the previous checks are passing? Make sure all
112
+ the above checks are successful before trying to make this one
113
+ pass
114
+ - try adding ssh keys to ssh-agent by executing
115
+ $ ssh-add ~/.ssh/id_rsa
116
+ - if the above does not work follow this guide to setup ssh-agent process
117
+ http://mah.everybody.org/docs/ssh
118
+ EOF
119
+ end
120
+
121
+ def local_keys_added_to_agent_error(_)
122
+ <<-EOF.gsub(/^\s+/, '')
123
+ It seems local ssh-agent process has no loaded keys.
124
+
125
+ Actions:
126
+ - add ssh private key to ssh-agent with this command
127
+ $ ssh-add /path/to/ssh_private_key
128
+ If ssh private key is in a standard location, then you most likely need this
129
+ $ ssh-add ~/.ssh/id_rsa
130
+ EOF
131
+ end
132
+
133
+ def local_repo_access_error(_)
134
+ <<-EOF.gsub(/^\s+/, '')
135
+ It seems git application repository cannot be accessed from local machine.
136
+
137
+ Actions:
138
+ - here's a guide to setting passwordless access to github repositories.
139
+ You should most likely follow just steps 3 and 4 from the guide if
140
+ all the previous checks are successful.
141
+ https://help.github.com/articles/generating-ssh-keys#step-3-add-your-ssh-key-to-github
142
+ EOF
143
+ end
144
+
145
+ def remote_agent_running_error(hosts)
146
+ msg = "It seems Capistrano did not succeed in making ssh agent forwarding for these hosts:\n"
147
+ msg << hosts.join(', ')
148
+ msg.concat "\n"
149
+ msg.concat <<-EOF.gsub(/^\s+/, '')
150
+ Actions:
151
+ - make sure all the previous checks pass
152
+ EOF
153
+ end
154
+
155
+ def remote_repo_access_error(hosts)
156
+ msg = "It seems Capistrano cannot access application git repository from these hosts:\n"
157
+ msg << hosts.join(', ')
158
+ msg.concat "\n"
159
+ msg.concat <<-EOF.gsub(/^\s+/, '')
160
+ Actions:
161
+ - make sure all the previous checks pass. That should make this one work too.
162
+ EOF
163
+ end
164
+
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,5 @@
1
+ module Capistrano
2
+ module SshDoctor
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,117 @@
1
+ require 'capistrano/ssh_doctor/dsl'
2
+
3
+ namespace :ssh do
4
+
5
+ namespace :config do
6
+
7
+ task :git do
8
+ unless fetch(:scm) == :git
9
+ puts 'It seems you are NOT using git as a Capistrano strategy. At the moment capistrano-ssh-doctor supports only git.'
10
+ puts 'Please change `scm` setting to `:git`.'
11
+ exit 1
12
+ end
13
+ end
14
+
15
+ task :repo_url do
16
+ if fetch(:repo_url) =~ /^http/
17
+ report.report_error_for('config_repo_url')
18
+ end
19
+ end
20
+
21
+ task :password do
22
+ hosts = []
23
+ on release_roles :all do
24
+ if host.netssh_options[:password]
25
+ hosts << host
26
+ end
27
+ end
28
+ report.report_error_for('config_password', hosts) if hosts.any?
29
+ end
30
+
31
+ task :agent_forwarding do
32
+ hosts = []
33
+ on release_roles :all do
34
+ unless host.netssh_options[:forward_agent]
35
+ hosts << host
36
+ end
37
+ end
38
+ report.report_error_for('config_agent_forwarding', hosts) if hosts.any?
39
+ end
40
+
41
+ end
42
+
43
+ namespace :local do
44
+
45
+ task :private_key_exists do
46
+ specified_keys = fetch(:ssh_options, {})[:keys] || ''
47
+ unless File.exists?(File.expand_path('~/.ssh/id_rsa')) ||
48
+ File.exists?(File.expand_path('~/.ssh/id_dsa')) ||
49
+ File.exists?(specified_keys)
50
+ report.report_error_for('local_private_key_exists')
51
+ end
52
+ end
53
+
54
+ task :agent_running_env_var do
55
+ unless ENV.include?('SSH_AUTH_SOCK')
56
+ report.report_error_for('local_agent_running_env_var')
57
+ end
58
+ end
59
+
60
+ task :agent_running_ssh_add do
61
+ if !system('ssh-add -l')
62
+ if $? == 2
63
+ report.report_error_for('local_agent_running_ssh_add')
64
+ elsif $? == 1
65
+ report.report_error_for('local_keys_added_to_agent')
66
+ end
67
+ end
68
+ end
69
+
70
+ task :repo_access do
71
+ unless system({ 'GIT_ASKPASS' => '/bin/echo' }, "git ls-remote #{fetch(:repo_url)}")
72
+ report.report_error_for('local_repo_access')
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ namespace :remote do
79
+
80
+ task :agent_running do
81
+ hosts = []
82
+ on release_roles :all do
83
+ if capture(:echo, '$SSH_AUTH_SOCK').empty?
84
+ hosts << host
85
+ end
86
+ end
87
+ report.report_error_for('remote_agent_running', hosts) if hosts.any?
88
+ end
89
+
90
+ task repo_access: :'git:wrapper' do
91
+ hosts = []
92
+ on release_roles :all do
93
+ with fetch(:git_environmental_variables) do
94
+ hosts << host unless strategy.check
95
+ end
96
+ end
97
+ report.report_error_for('remote_repo_access', hosts) if hosts.any?
98
+ end
99
+
100
+ end
101
+
102
+ desc 'Perform ssh doctor checks'
103
+ task :doctor do
104
+ invoke 'ssh:config:git'
105
+ invoke 'ssh:config:repo_url'
106
+ invoke 'ssh:config:password'
107
+ invoke 'ssh:config:agent_forwarding'
108
+ invoke 'ssh:local:private_key_exists'
109
+ invoke 'ssh:local:agent_running_env_var'
110
+ invoke 'ssh:local:agent_running_ssh_add'
111
+ invoke 'ssh:local:repo_access'
112
+ invoke 'ssh:remote:agent_running'
113
+ invoke 'ssh:remote:repo_access'
114
+ report.print
115
+ end
116
+
117
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-ssh-doctor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Bruno Sutic
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capistrano
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: |
42
+ This plugin helps you setup and debug `ssh-doctor` forwarding for Capistrano
43
+ deployment.
44
+ It peforms a number of checks on the local machine as well as on the
45
+ servers. Report output with suggested next steps is provided in case there
46
+ are any errors with the setup.
47
+ email:
48
+ - bruno.sutic@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - CHANGELOG.md
54
+ - LICENSE.md
55
+ - README.md
56
+ - Rakefile
57
+ - capistrano-ssh-doctor.gemspec
58
+ - lib/capistrano-ssh-doctor.rb
59
+ - lib/capistrano/ssh_doctor.rb
60
+ - lib/capistrano/ssh_doctor/dsl.rb
61
+ - lib/capistrano/ssh_doctor/report.rb
62
+ - lib/capistrano/ssh_doctor/report/messages.rb
63
+ - lib/capistrano/ssh_doctor/version.rb
64
+ - lib/capistrano/tasks/ssh_doctor.rake
65
+ homepage: https://github.com/bruno-/capistrano-ssh-doctor
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.1.5
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: This plugin helps you setup and debug `ssh-doctor` forwarding for Capistrano
89
+ deployment.
90
+ test_files: []