Capistrano部署失败,出现git:check - Permission denied (publickey)错误

9

本地操作系统:Windows 10 Pro(使用Git Bash作为我的终端)

暂存服务器操作系统:Ubuntu 16.04 LTS

我一直在努力让基本的Capistrano部署在我的暂存服务器上工作。 我遵循了这篇指南来设置Capistrano。

部署过程总是在git:check阶段失败,因为据称没有权限访问我在GitLab上的repo。 我确定我的SSH代理转发正在工作,因为我能够使用我的SSH密钥SSH进入我的服务器并访问GitLab。 SSH密钥未存储在我的服务器上:

$ ssh deploy@myserver.com

deploy@MyServer:~$ ssh -T git@gitlab.com
debug1: client_input_channel_open: ctype auth-agent@openssh.com rchan 2 win 65536 max 16384
debug1: channel 1: new [authentication agent connection]
debug1: confirm auth-agent@openssh.com
Welcome to GitLab, Alexander!debug1: channel 1: FORCE input drain

迄今为止,关于这个问题的所有问题都没有对我起作用。

以下是我的部署文件:

deploy.rb

set :application, "myapp"
set :branch, "master"
set :repo_url, "git@gitlab.com:MyApp/myapp.git"

# Defaults to false
# Skip migration if files in db/migrate were not modified
set :conditionally_migrate, true

set :ssh_options, { forward_agent: true }

set :rvm_ruby_version, '2.2.6'

# Default deploy_to directory is /var/www/my_app_name
set :deploy_to, "/var/www/#{fetch(:application)}/"
set :deploy_user, "deploy"

# Tells Capistrano to store config/database.yml file inside a directory called /shared, which is meant for any files
# we want to persist between deploys
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')

# Directories that are meant to persist between deploys, and they will also be stored inside /shared
set :linked_dirs, fetch(:linked_dirs, []).push('bin', 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

# The specs that should be run before deployment is allowed to continue
set :tests, []

# Delayed Job Config: https://github.com/AgileConsultingLLC/capistrano3-delayed-job
set :delayed_job_workers, 3

# Keep the last 5 deploys for rollback purposes
set :keep_releases, 5

namespace :deploy do
  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do
      # Here we can do anything such as:
      # within release_path do
      #   execute :rake, 'cache:clear'
      # end
    end
  end
end

staging.rb

set :stage, :staging
set :rails_env, :staging

role :app, %w{deploy@myserver.com}
role :web, %w{deploy@myserver.com}
role :db,  %w{deploy@myserver.com}

当我部署时,这里是Capistrano的调试日志:

$ bundle exec cap staging deploy --trace
** Invoke staging (first_time)
** Execute staging
** Invoke load:defaults (first_time)
** Execute load:defaults
** Invoke rvm:hook (first_time)
** Invoke passenger:rvm:hook (first_time)
** Invoke passenger:test_which_passenger (first_time)
** Execute passenger:test_which_passenger
** Execute passenger:rvm:hook
** Execute rvm:hook
** Invoke rvm:check (first_time)
** Execute rvm:check
rvm 1.29.3 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]
ruby-2.2.6
ruby 2.2.6p396 (2016-11-15 revision 56800) [x86_64-linux]
** Invoke bundler:map_bins (first_time)
** Invoke passenger:bundler:hook (first_time)
** Execute passenger:bundler:hook
** Execute bundler:map_bins
** Invoke deploy:set_rails_env (first_time)
** Execute deploy:set_rails_env
** Invoke deploy:set_linked_dirs (first_time)
** Execute deploy:set_linked_dirs
** Invoke deploy:set_rails_env
** Invoke deploy (first_time)
** Execute deploy
** Invoke deploy:starting (first_time)
** Execute deploy:starting
** Invoke deploy:check (first_time)
** Invoke git:check (first_time)
** Invoke git:wrapper (first_time)
** Execute git:wrapper
00:00 git:wrapper
      01 mkdir -p /tmp01 deploy@myserver.com 0.286s
      Uploading /tmp/git-ssh-myapp-staging-localuser.sh 100.0%
      02 chmod 700 /tmp/git-ssh-myapp-staging-localuser.sh
    ✔ 02 deploy@myserver.com 0.277s
** Execute git:check
00:01 git:check
      01 git ls-remote git@gitlab.com:MyApp/myapp.git HEAD
      01 Permission denied (publickey).
      01 fatal: Could not read from remote repository.
      01
      01 Please make sure you have the correct access rights
      01 and the repository exists.
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as deploy@myserver.com: git exit status: 128
git stdout: Nothing written
git stderr: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/runners/parallel.rb:15:in `rescue in block (2 levels) in execute'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/runners/parallel.rb:11:in `block (2 levels) in execute'

Caused by:
SSHKit::Command::Failed: git exit status: 128
git stdout: Nothing written
git stderr: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/command.rb:99:in `exit_status='
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/backends/netssh.rb:169:in `execute_command'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/backends/abstract.rb:141:in `block in create_command_and_execute'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/backends/abstract.rb:141:in `tap'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/backends/abstract.rb:141:in `create_command_and_execute'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/backends/abstract.rb:74:in `execute'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/capistrano-3.10.1/lib/capistrano/scm/git.rb:77:in `git'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/capistrano-3.10.1/lib/capistrano/scm/git.rb:38:in `check_repo_is_reachable'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/capistrano-3.10.1/lib/capistrano/scm/tasks/git.rake:19:in `block (4 levels) in eval_rakefile'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/backends/abstract.rb:93:in `with'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/capistrano-3.10.1/lib/capistrano/scm/tasks/git.rake:18:in `block (3 levels) in eval_rakefile'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/backends/abstract.rb:29:in `instance_exec'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/backends/abstract.rb:29:in `run'
C:/Ruby22/lib/ruby/gems/2.2.0/gems/sshkit-1.15.1/lib/sshkit/runners/parallel.rb:12:in `block (2 levels) in execute'
Tasks: TOP => deploy:check => git:check
The deploy has failed with an error: Exception while executing as deploy@myserver.com: git exit status: 128
git stdout: Nothing written
git stderr: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
** Invoke deploy:failed (first_time)
** Execute deploy:failed


** DEPLOY FAILED
** Refer to log/capistrano.log for details. Here are the last 20 lines:


 DEBUG [6b6ba2d0] Finished in 0.471 seconds with exit status 0 (successful).

 DEBUG [c6e2d7dc] Running ~/.rvm/bin/rvm 2.2.6 do ruby --version as deploy@myserver.com

 DEBUG [c6e2d7dc] Command: ~/.rvm/bin/rvm 2.2.6 do ruby --version

 DEBUG [c6e2d7dc]       ruby 2.2.6p396 (2016-11-15 revision 56800) [x86_64-linux]

 DEBUG [c6e2d7dc] Finished in 0.608 seconds with exit status 0 (successful).

  INFO [fd5500a8] Running /usr/bin/env mkdir -p /tmp as deploy@myserver.com

 DEBUG [fd5500a8] Command: /usr/bin/env mkdir -p /tmp

  INFO [fd5500a8] Finished in 0.286 seconds with exit status 0 (successful).

 DEBUG Uploading /tmp/git-ssh-myapp-staging-localuser.sh 0.0%

  INFO Uploading /tmp/git-ssh-myapp-staging-localuser.sh 100.0%

  INFO [f33d4873] Running /usr/bin/env chmod 700 /tmp/git-ssh-myapp-staging-localuser.sh as deploy@myserver.com

 DEBUG [f33d4873] Command: /usr/bin/env chmod 700 /tmp/git-ssh-myapp-staging-localuser.sh

  INFO [f33d4873] Finished in 0.277 seconds with exit status 0 (successful).

  INFO [86d3cd5a] Running /usr/bin/env git ls-remote git@gitlab.com:MyApp/myapp.git HEAD as deploy@myserver.com

 DEBUG [86d3cd5a] Command: ( export GIT_ASKPASS="/bin/echo" GIT_SSH="/tmp/git-ssh-myapp-staging-localuser.sh" ; /usr/bin/env git ls-remote git@gitlab.com:MyApp/myapp.git HEAD )

 DEBUG [86d3cd5a]       Permission denied (publickey).

 DEBUG [86d3cd5a]       fatal: Could not read from remote repository.



Please make sure you have the correct access rights

and the repository exists.

我已经尝试手动在本地和远程服务器上运行Capistrano尝试的命令,它们都成功了。我真的很困惑,非常感谢任何帮助!


你尝试在服务器的~/.ssh/config中设置它了吗? - Roman Kiselenko
@Зелёный 我按照GitHub上的这个指南设置了SSH代理转发,但我不确定在服务器的~/.ssh/config下需要设置什么。你能否请澄清一下? - Alexander
这可能有点傻,但你能否尝试不使用set :ssh_options, { forward_agent: true } - will_in_wi
@will_in_wi 谢谢你的建议。我已经尝试过不使用 ssh_options,但遗憾的是仍然无法工作。 - Alexander
看起来Capistrano的行为与正常的SSH有所不同,原因不明。你已经成功地让SSH代理在正常的SSH中工作了。我想知道你运行Capistrano的上下文是否没有加载密钥。ssh-add - will_in_wi
显示剩余3条评论
6个回答

7
请按照以下步骤将您的公钥添加到存储库设置中的部署密钥列表中:

本地机器设置:

  1. Check if your local system has ~/.ssh/id_rsa.pub key file. If not, create a new one:

    $ ssh-keygen -t rsa
    
  2. Add the newly created public key ~/.ssh/id_rsa.pub to the repository's deployment(access) keys in settings:

  3. Load the keys to ssh-agent:

    Check whether ssh-agent is running, If not, start the ssh agent

    $ ssh-agent /bin/bash
    

    Add the id_rsa key to the agent:

    $ ssh-add ~/.ssh/id_rsa
    

    Note: Sometimes, this step(Step - 3) needs to be done before each deployment if you receive "Access denied to the repository" error during deployment.

  4. Add your local SSH Key to deployment server Authorized Keys file (remember to replace the port number with your customized port number):

    $ cat ~/.ssh/id_rsa.pub | ssh -p port_num user@server_ip 'cat >> ~/.ssh/authorized_keys'
    

参考资料: https://www.digitalocean.com/community/tutorials/deploying-a-rails-app-on-ubuntu-14-04-with-capistrano-nginx-and-puma

deploy.rb

尝试按以下方式更改 deploy.rb 文件中的 ssh_options

set :ssh_options, { forward_agent: true, user: "deploy", auth_methods: ['publickey'], keys: %w(~/.ssh/privatekey.pem) }

请将~/.ssh/privatekey.pem替换为您的SSH私钥文件路径。
部署:
只需运行cap staging deploy即可将其部署到服务器。
在需要的情况下,将cap部署命令中的staging替换为环境。

1
谢谢您的回答。我已经使用了这些选项,但是我仍然收到相同的错误信息。user选项的值应该是我的服务器上的用户名还是GitLab上的用户名?两者都不起作用。 - Alexander
在您的服务器中,它应该是用户的名称。 - Gokul
@Alexander 我已经添加了更详细的步骤,请检查它是否解决了问题。尝试将“公钥”添加到仓库的部署(访问)密钥中。 - Gokul
我认为你错过了第二步。 - Gokul

6
感谢所有回答问题的人,我已经找到了解决方案!主要问题是Git Bash没有改变我的~/.ssh目录的权限为0700,当我运行chmod 700 ~/.ssh时。这导致在Capistrano部署时SSH代理转发无法工作,但是当我手动SSH登录到服务器时可以正常工作。我决定尝试使用Windows上的Ubuntu中的Bash(BUW)而不是Git Bash,结果我的部署成功了!我将与Git Bash完全相同的配置和密钥复制到了BUW上。唯一的区别是我能够更改BUW的~/.ssh目录的权限为0700。因此,以下是我的问题的解决方案: 1.创建一个部署密钥并将其添加到GitLab 正如@Onur、@grizzthedj和@Gokul M所指出的那样,我需要为GitLab创建一个部署密钥,并在我的服务器上授权它。以下是我如何做到这一点:
  1. 在本地机器上生成一个新的SSH密钥:ssh-keygen -t rsa -b 4096
  2. 复制公钥的输出:cat ~/.ssh/id_rsa.pub
  3. SSH登录到我的服务器
  4. 将公钥添加到~/.ssh/authorized_keys的末尾
  5. 回到我的本地机器,打开浏览器,登录GitLab,转到我的存储库页面,并将公钥粘贴到设置>存储库>部署密钥
2.使用BUW而不是Git Bash
  1. On my local machine, I set up BUW to start the SSH agent on session load using the instructions from this SO answer.
  2. Change the permissions on ~/.ssh: chmod 700 ~/.ssh
  3. Start the SSH agent and add my deploy key to it:

    eval $(ssh-agent -s)
    ssh-add ~/.ssh/id_rsa
    

我已经从我的deploy.rb文件中删除了set :ssh_options行,因为没有它也能正常工作。

就是这样!看起来我以后将使用BUW进行部署。


官方文档:https://capistranorb.com/documentation/getting-started/authentication-and-authorisation/ - Andrew Zelenets

2
根据您的cap deploy输出,看起来从您的笔记本电脑到服务器的SSH连接不是问题所在。
00:00 git:wrapper
      01 mkdir -p /tmp
    ✔ 01 deploy@myserver.com 0.286s
      Uploading /tmp/git-ssh-myapp-staging-localuser.sh 100.0%
      02 chmod 700 /tmp/git-ssh-myapp-staging-localuser.sh
    ✔ 02 deploy@myserver.com 0.277s 

这个问题出现在Capistrano尝试通过SSH运行git ls-remote git@gitlab.com:MyApp/myapp.git HEAD命令时。

你需要将公钥添加到GitLab中的SSH Keys中,因为SSH代理转发需要在所有目标系统上安装公钥。在你的情况下,GitLab是一个目标系统。

cat ~/.ssh/id_rsa.pub    # Copy the contents of your public key(filename may be different)

登录GitLab,将公钥粘贴到您的存储库的SSH密钥中(在存储库设置中找到),然后您就可以使用了。

您还需要在ssh_options中指定创建SSH密钥的用户。

set :ssh_options, {
    forward_agent: true,
    user: 'deploy',
}

感谢您的回答。使用SSH代理转发,如果我已经在本地环境中使用该密钥,那么一旦我通过SSH登录到服务器,代理不应该可以访问密钥吗?我已将公钥放入服务器上的“authorized_keys”文件中。 - Alexander
您的本地环境和服务器之间的SSH连接不是问题。问题在于您的服务器与GitLab之间的连接。我已经更新了我的答案(请参见EDIT部分)。 - grizzthedj
当你部署到staging时,你是从本地工作站运行capistrano,还是在另一台服务器上运行? - grizzthedj
我正在从我的本地工作站运行 cap staging deploy - Alexander
如果您以deploy用户身份通过SSH登录到您的staging服务器,并运行git ls-remote git@gitlab.com:MyApp/myapp.git HEAD,是否成功? - grizzthedj
显示剩余4条评论

1
你还需要将远程服务器的公钥定义到仓库中。显然,你的电脑可以访问该仓库,但服务器却不能。要获取默认的公钥,你可以查看~/.ssh/id_rsa.pub,或使用ssh-keygen -t rsa -b 4096 -C "your_email@example.com"生成一个公钥。不要忘记在服务器上使用ssh-add来初始化公钥。希望这能帮到你。

0

对于未来遇到此问题的人寻找替代方案:

大多数关于此问题的搜索都建议添加SSH密钥。如果您确定已经添加了它们,并且ssh -T git@bitbucket.org(或您正在使用的任何git服务)显示您已登录,并且代理转发已设置,当在Windows上遇到相同问题时,我尝试安装PuTTY,并成功解决了问题。安装后:

  • 打开PuTTYGen > 转换 > 导入密钥(如果您有要使用的密钥;否则,请生成一个新密钥)
  • 运行Pageant(与PuTTY一起提供)
  • 在系统托盘中找到Pageant,右键单击,然后“添加密钥”
  • 添加上述密钥
  • 像以前一样运行cap deploy
我在一篇不同的SO文章中发现了这种方法,该方法涉及Capistrano在Windows上使用时出现的响应长度错误(链接1),因此这种方法在这些情况下也可以运行。这可能是因为Windows上的net-ssh需要Pageant才能正常工作

0

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