Capistrano在部署时尽管使用SSH密钥,仍会要求密码。

59

我肯定我的ssh密钥已经正确设置,因为我在使用ssh时从未提示输入密码。但是当我使用cap deploy部署时,capistrano仍然会要求密码。不过,当我用cap deploy:setup进行设置时,它却没有要求密码,这很奇怪。如果没有密码提示,部署周期将更加顺畅。

具体而言,我要将Sinatra应用程序部署到Dreamhost共享账户(使用Passenger)。我以前曾经遵循过某个教程进行部署,那时候完美地运行了。但现在似乎出了一些问题。我正在使用capistrano(2.5.9)和git版本1.6.1.1。这是我的Capfile:

load 'deploy' if respond_to?(:namespace) # cap2 differentiator

set :user, 'ehsanul'
set :domain, 'jellly.com'

default_run_options[:pty] = true

# the rest should be good
set :repository,  "ehsanul@jellly.com:git/jellly.git"
set :deploy_to, "/home/ehsanul/jellly.com"
set :deploy_via, :remote_cache
set :scm, 'git'
set :branch, 'deploy'
set :git_shallow_clone, 1
set :scm_verbose, true
set :use_sudo, false

server domain, :app, :web

namespace :deploy do
  task :migrate do
    run "cd #{current_path}; /usr/bin/rake migrate environment=production"
  end
  task :restart do
    run "touch #{current_path}/tmp/restart.txt"
  end
end

after "deploy", "deploy:migrate"

以下是我运行cap deploy命令后的输出结果,直到出现密码提示:

$ cap deploy
  * executing `deploy'
  * executing `deploy:update'
 ** transaction: start
  * executing `deploy:update_code'
    updating the cached checkout on all servers
    executing locally: "git ls-remote ehsanul@jellly.com:git/jellly.git deploy"
/usr/local/bin/git
  * executing "if [ -d /home/ehsanul/jellly.com/shared/cached-copy ]; then cd /home/ehsanul/jellly.com/shared/cached-copy && git fetch  origin && git reset  --hard ea744c77b0b939d5355ba2dc50ef1ec85f918d66 && git clean  -d -x -f; else git clone  --depth 1 ehsanul@jellly.com:git/jellly.git /home/ehsanul/jellly.com/shared/cached-copy && cd /home/ehsanul/jellly.com/shared/cached-copy && git checkout  -b deploy ea744c77b0b939d5355ba2dc50ef1ec85f918d66; fi"
    servers: ["jellly.com"]
    [jellly.com] executing command
 ** [jellly.com :: out] ehsanul@jellly.com's password:
Password:
 ** [jellly.com :: out]
 ** [jellly.com :: out] remote: Counting objects: 7, done.
remote: Compressing objects: 100% (4/4), done.

可能出了什么问题?

7个回答

72

在我的本地机器上执行ssh-add ~/.ssh/id_rsa,解决了我的问题。看起来当使用Capistrano调用ssh命令行工具时,它无法检测到我的身份。


4
我将该命令添加到了我的bash_profile文件中,这样我就可以确保在启动新的终端会话时加载默认身份。 - Pablo Torrecilla
这对我也解决了问题,但是似乎每隔一段时间(看起来很随机),我就不得不再次运行它。 - sandre89
不确定是升级到OSX Sierra还是其他原因,但我也不得不做同样的事情。 - Joel Grannas
这是一个非常棒的复制/粘贴答案,真是救了我们的一天!谢谢。 - chosta
我在macOS Sierra上使用Capistrano 3部署Rails应用程序时遇到了问题(在Yosemite上一切正常),每次都提示我输入密码(但是在Capistrano 2中一切顺利)。通过使用此链接解决了问题-https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#adding-your-ssh-key-to-the-ssh-agent - Michael Klishevich
我的电脑重启后,这个解决方案对我来说不起作用。还有其他人遇到这个问题吗? - Joel Grannas

56

密码提示是因为您部署的服务器正在连接git服务器并需要进行身份验证。由于您本地计算机(从中部署)已经具有有效的ssh密钥,请在Capfile中启用转发以使用该密钥:

set :ssh_options, {:forward_agent => true}

它将本地计算机的身份验证信息转发到部署服务器尝试连接到您的git服务器时。

这比在部署服务器上放置您的私钥要好得多!

另一种解决服务器在ssh回自己时避免密码提示的方法是告诉capistrano不要这样做。感谢Daniel Quimper的 capistrano-site5 GitHub存储库的'读我'部分,我们注意到以下内容:

set :deploy_via, :copy

显然,这适用于应用程序和Git仓库都托管在同一主机上的情况。但我想我们中的一些人正在这样做 :)


3
我没有将我的私钥放在服务器上。我只是将部署服务器的公钥添加到它自己的“authorized_keys”列表中。这是因为部署服务器也是我的git服务器,显然由于Capistrano的工作方式,它会尝试通过ssh登录自己,导致需要密码登录。因此,我基本上只是在服务器和自身之间设置了ssh密钥。这比将我的私钥置于外界更安全;) 不过,我会尝试使用forward_agent,看起来更简洁。谢谢! :) - ehsanul
如果有其他人想知道为什么这个方法有效以及它在哪里有记录,这些是Net:SSH的选项,请参阅"http://net-ssh.github.com/ssh/v1/chapter-2.html"中的"Options"部分。 - oseiskar
1
顺便说一句,如果你仍然遇到问题,特别是在使用自定义命名密钥时,请尝试这样做:ssh_options[:keys] = [File.join(ENV["HOME"], ".ssh", "my_custom_id_rsa")] - Mario Uher

18

我也遇到了同样的问题。

这行代码没有起作用:

set :ssh_options, {:forward_agent => true}

然后我按照Dreamhost wiki上所述执行了所提到的内容

[local ~]$ eval `ssh-agent`
[local ~]$ ssh-add ~/.ssh/yourpublickey  # omit path if using default keyname

现在我可以无需密码进行部署。


2
那行代码本身不应该起作用。它只是启用代理转发。如果您一开始没有运行代理,它也不会有太大帮助。 - Sam Figueroa
2
你应该添加私钥,而不是公钥。 - DaveStephens
我经常这样做,但仍然要求密码。我的配置是 set :ssh_options, { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) } - Amit Patel
您可能还想将添加到项目设置的ssh私钥指纹添加到config.yml中... - Funso Popoola

3
记录显示,在通过SSH登录jellly.com后,它提示输入密码,因此看起来实际的git更新正在提示输入密码。
我认为这是因为您的存储库设置指定了您的git用户,即使在这种情况下您可以匿名访问它。
您应该创建一个匿名的git帐户并将您的repo行更改为以下内容:
set :repository,  "git@jellly.com:git/jellly.git"

另外,你也可以将你的SSH密钥放在生产服务器上,但这似乎没有什么用处。你还可以配置SSH将认证请求通过初始的SSH连接进行转发。不过,使用匿名只读源代码控制来部署可能更容易。


2
谢谢,问题已解决!看起来设置另一个用户也可以解决问题,但我只是让服务器的SSH密钥被授权给自己 - 简单又不会有安全风险。使用了以下命令:cat ~/.ssh/id_rsa.pub | ssh ehsanul@jellly.com 'cat >> .ssh/authorized_keys' - ehsanul
嗯,实际上,只指定 set:repository, /home/ehsanul/git/jellly.git 也可以工作,不需要 SSH。编辑:不行,不起作用。 - ehsanul
很高兴你解决了这个问题。在服务器上保存私钥是一种安全风险,你应该只在那里存储公钥。至少这证实了问题所在。我建议你使用匿名或有限访问账户,而不是将私钥发布到应用服务器上。 - Winfield
只是澄清一下,我没有把我的私钥放在服务器上。请看我对另一个答案的评论了解我做了什么。 - ehsanul
@ehsanul:我认为在本地计算机上执行ssh-copy-id username@server正是您的cat-pipe-stunt所做的事情 =)。 - Besi

1

我将本地机器的id_rsa.pub密钥复制并粘贴到远程服务器的authorized_key文件中,它起作用了。


1
将公钥手动复制到authorized_keys中在我的情况下没有起作用,但通过服务进行操作时成功了。当我发现服务只是在末尾添加了一个相同的密钥时。
ssh-copy-id -i ~/.ssh/id_rsa.pub user@remote

0

如果您使用的是Windows工作站(便携式),有时会直接连接到内部公司网络,有时会通过VPN连接,您可能会发现在运行cap远程任务时会出现不一致的行为,要求您输入密码。

在我的情况下,我们公司有登录脚本,当您已经连接到公司局域网并登录时执行该脚本,将您的HOME目录设置为网络共享位置。如果您使用缓存凭据登录,然后再通过VPN登录,则登录脚本不会设置您的主目录。存储您的私钥的.ssh目录可能仅存在于其中一个位置。

在这种情况下,一个简单的解决方法就是将具有.ssh目录的HOME复制到没有它的目录中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接