Capistrano asks for password when deploying, despite SSH keys - ruby-on-rails

My ssh keys are definitely set up correctly, as I'm never prompted for the password when using ssh. But capistrano still asks for a password when deploying with cap deploy. It doesn't ask for the password when I setup with cap deploy:setup though, strangely enough. It would make the deployment cycle so much smoother without a password prompt.
Specifics: I'm deploying a Sinatra app to a Dreamhost shared account (which uses Passenger). I had followed a tutorial for doing so long back, which worked perfectly back then. Something broke since. I'm using capistrano (2.5.9) and git version 1.6.1.1. Here's my 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"
And here's the output of what happens when I cap deploy, upto the password prompt:
$ 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.
What could be broken?

Executing ssh-add ~/.ssh/id_rsa in my local machine fixed the issue for me. It seemed that the ssh command line tool wasn't detecting my identity when called with Capistrano.

The password prompt is because the server you are deploying to is connecting to the git server and needs authentication. Since your local machine (where you are deploying from) already has a valid ssh-key, use that one by enabling forwarding in your Capfile:
set :ssh_options, {:forward_agent => true}
That forwards the authentication from your local machine through when the deployment server tries to connect to your git server.
This is much preferred to putting your private key out on the deployment server!
Another way of getting around the password prompt when the server is ssh'ing back on itself is to tell capistrano not to do so. Thanks to the 'readme' section for Daniel Quimper's capistrano-site5 github repo, we note the following:
set :deploy_via, :copy
Obviously, this works for the case where both the app and git repository are being hosted on the same host. But I guess some of us are doing that :)

I've had the same problem.
This line did'nt work:
set :ssh_options, {:forward_agent => true}
Then I executed mentioned on Dreamhost wiki
[local ~]$ eval `ssh-agent`
[local ~]$ ssh-add ~/.ssh/yourpublickey # omit path if using default keyname
And now I can deploy without password.

The logs show it prompted for a password after logging in via SSH to jellly.com, so it looks like the actual git update is prompting for a password.
I think this is because your repository setting specifies your git user, even though you can access it anonymously in this case.
You should create an anonymous git account and change your repo line like this:
set :repository, "git#jellly.com:git/jellly.git"
Alternatively, you could put your SSH key ON your production server, but that doesn't sound useful. You also might be able to configure SSH to forward authentication requests back through the initial SSH connection. The anonymous read-only source control for deploy is likely easier, though.

I copy and paste my local machie id_rsa.pub key to remote server authorized_key file and it worked

copying public key manually to authorized_keys did not work in my case but doing it via service worked, when I found service had simply added one more same key at the end
ssh-copy-id ~/.ssh/id_rsa.pub user#remote

If you're using a Windows workstation (portable) that you sometimes dock directly into an internal corporate network and sometimes connect via VPN, you may find that you get inconsistent behavior in running cap remote tasks asking you for a password.
In my situation, our company has login scripts that execute when you logged in while already connected to the company LAN that set your HOME directory to a network share location. If you login from cached credentials and then VPN in, your home directory isn't set by the login script. The .ssh directory that stores your private key may be in only one of those locations.
An easy fix in that situation is to just copy the .ssh directory from the HOME that has it to the one that doesn't.

Related

SSH agent forwarding with Capistrano 3 not working when deploying Rails app

I have the following setup in my deploy.rb
set :application, 'sample_app'
set :repo_url, 'user#123.45.67.100:/home/user/railsapps/sample_app'
set :deploy_to, '/var/www/sample_app'
set :user, "user"
set :ssh_options, { :forward_agent => true }
and my deploy/production.rb file:
set :stage, :production
server '123.45.67.200', user: 'user', roles: %w{app db web}
I get the following error when I run cap production deploy:check
DEBUG [] ssh: connect to host 123.45.67.100 port 22: Connection timed out
DEBUG [] fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists.
(Backtrace restricted to imported tasks)
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as user#123.45.67.200: git exit status: 128
git stdout: Nothing written
git stderr: ssh: connect to host 123.45.67.200 port 22: Connection timed out
fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists.
In one of the lines, I see that it tries to access the repository as user#123.45.67.200, which is the deployment user for the production server:
INFO [] Running /usr/bin/env git ls-remote --heads user#123.45.67.100:/home/user/railsapps/sample_app as user#123.45.67.200
Shouldn't it be saying that it's connecting as the local user with the local ssh keys? Is Capistrano logging into the production server and then pulling code from the repository? If it is, is there a way to make it push code from the repository to the production server?
It appears that your Git URL is not valid. You can test this by connecting to the remote system (user#123.45.67.200) and try to hit the remote Git repo with a simple git ls-remote --heads which will prove connectivity.
git ls-remote --heads user#123.45.67.100:/home/user/railsapps/sample_app
I suspect that you might need .git appended to your URL (user#123.45.67.100:/home/user/railsapps/sample_app.git) but that really depends on how you have your remote repo set up.
Git does use SSH to connect but it doesn't explicitly show that in the Capistrano output. All you will see are the explicit git commands.
Alternatively, if you are expecting to use agent forwarding then you might be experiencing an issue with your ssh forwarding config, either local or remote. You can test that by checking your local machine then connecting to a remote machine and seeing if your identity was forwarded. You would do that like this:
local-host$ ssh-add -l
local-host$ ssh user#remote-host
remote-host$ ssh-add -l
If you see output like:
Error connecting to agent: No such file or directory
or:
Could not open a connection to your authentication agent.
or:
The agent has no identities.
Then you need to sort out that issue before Capistrano will work as expected.
You can checkout this write up "Using ssh-agent with ssh" to help with SSH config.
Capistrano will log into the server, and then from the server pull down the code from your VCS.
There are usually two ways of authenticating this:
ssh-agent forwarding which will give the remote session access to your developer key, or
deploy keys which will give the server user's key access to your code.
The second half of this documentation page describes the way Git works with Capistrano: http://capistranorb.com/documentation/getting-started/cold-start/
From the errors you have posted, you probably need to set up one or the other of the above options.

Connect to github from linode with Capistrano deploy gives permission denied to public key

This is my first time using linode and uploading a Rails app to a VPS, so I might of skipped something obvious.
I followed two tutorials
Ryan Bates video to deploying to a vps
and
David's answer on Stackoverflow
I am at the point where I want to deploy my rails app on Linode (Ubuntu 13.10)
When I execute the command bundle exec cap deploy:update
I get the errors that Linode cannot connect to github due to a public key
user:my-app User$ bundle exec cap deploy:update
* 2014-02-12 17:19:46 executing `deploy:update'
** transaction: start
* 2014-02-12 17:19:46 executing `deploy:update_code'
updating the cached checkout on all servers
executing locally: "git ls-remote git#github.com:user/my-app.git master"
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
*** [deploy:update_code] rolling back
* executing "rm -rf /home/user/apps/my-app/releases/20140212091953; true"
servers: ["XXX.XXX.XX.XX"]
[XXX.XXX.XX.XX] executing command
command finished in 4607ms
Command git ls-remote git#github.com:user/my-app.git master returned status code pid 1529 exit 128
On my local machine I have no problem to commit and push my app on Github and I have RSA Keys on my local computer. It just asks me to login with my username and password each time I push my app.
On linode from the shell, I can connect to github by using ssh -vT git#github.com. I do have the RSA keys on the linode server and I added the ssh-agent using ssh-add
my deploy.rb
set :application, "my-app"
set :user, "user"
set :deploy_to, "/home/#{user}/apps/#{application}"
set :deploy_via, :remote_cache
set :use_sudo, false
set :keep_releases, 3
default_run_options[:pty] = true
set :scm, :git
set :repository, "git#github.com:user/#{application}.git"
set :ssh_options, { :forward_agent => true }
# ssh_options[:forward_agent] = true
set :branch, "master"
I am a bit at a loss.
EDIT: I have a private repository
I just moved from Linux to Mac OSx. Thus, I have imported whole .ssh folder from linux to mac. While moving from linux to linux it worked, but to make it work on Mac, I had also to run:
ssh-add
That's the whole fix ;) See http://peteoliveira.com/deploying-with-capistrano-3-failing-permission-denied-publickey/ for more info.
So I found the solution to this github connection. I actually have another problem with the deployment where the bundle install fails. Anyways here is what I learned and I hope it will help others.
What you need to know:
With Capistrano when you wish to push your public or private Github
repository onto your VPS server, you need to make sure that BOTH your
server and your computer has an SSH access with Github.
Even if you can git push origin master it doesn't mean you have SSH
access with Github. Here is how you troubleshoot:
A) Make sure you can SSH access from your computer
Make sure you have Git installed on your machine Set up Git
tutorial
Make sure that you have an SSH Key on your local machine (with Linux
or Mac)
cd ~/.ssh then
ls -a
and look for the files id_rsa and id_rsa.pub
If you don't have these rsa files, follow this tutorial
Generating SSH keys
Copy your SSH key
pbcopy < ~/.ssh/id_rsa.pub
# Copies the contents of the id_rsa.pub file to your clipboard
Login with your browser on http://www.github.com and go to
your_username -> edit profile -> settings -> ssh keys
https://github.com/settings/ssh. Click the button Add keys, add the name that identifies your comptuter and paste the key code that you previously copied.
Make sure you have SSH Agent on. In Terminal type
ssh-add #enter a passphrase if you want to (recommended)
Test if you can SSH with Github
ssh git#github.com
The first time it may ask you to accept the connection.
You should get the following response
PTY allocation request failed on channel 0
Hi username! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
You can also make sure that your id_rsa is properly found by running
ssh -vT git#github.com
# make sure that this line is not -1 (it means it couldn't find the file)
=> debug1: identity file /Users/YOUR_USERNAME/.ssh/id_rsa type 1
Now you shouldn't have permission denied (Public Key)
B) Make sure you can SSH access from your server
Run ssh root#your_server_ip_address if you didn't setup a user on your server or ssh username#your_server_ip_address. You will then be within the server shell and you want to repeat the same process for your computer.
NOTE: The server SSH Keys will be different than your computer. That means that on Github you need to add 2 SSH Keys, one for your computer and one for your server. That is why you need to repeat the process on both machines. Also to keep it simple, do not try to have more than one SSH Key on each machine.
NOTE 2: In your server after you generated your SSH key, to copy it run the command cat ~/.ssh/id_rsa.pub
Once both your computer and the server are accepted on Github, then you can update your rails app using capistrano and your Github repository. Yay!

Capistrano local git repository cloning to remote asks for password despite SSH keys

Totally new to Capistrano.
I have a local git repository that I want to publish to my remote server. I've followed other answers here and came up with this configuration:
require 'bundler/capistrano'
set :application, "app_name"
set :repository, '~/Dropbox/app/.git'
set :user, 'user_name'
set :deploy_to, 'ssh://remote_host/~/railsApps/app_name'
set :scm_verbose, true
set :deploy_via, :copy
default_run_options[:pty] = true
server "remote_server", :web, :app, :db, :primary => true
set :scm, :git
set :branch, "master"
ssh_options[:keys] = %w(~/.ssh/id_rsa)
after "deploy:restart", "deploy:cleanup"
This no longer asks for a password for the remote server, but fails always with the following error:
The --deployment flag requires a Gemfile.lock. Please make sure you have checked your Gemfile.lock into version control before deploying.
I am definitely including the Gemfile.lock file in my git repo.
If I change the Capistrano configuration to clone from the remote git folder to which I push (which is in that same server) then I don't get an error but it asks for my password every time I try to connect.
Help please.
Note that SSH key pairing works fine when used from the CLI for regular SSH connection.
Solution
Thanks to Tigraine I was able to solve it. In the hopes that this helps someone else, here is what finally did the trick:
Tigraine is correct in that the paths are local to the remote server, but I was getting an error when trying to use local paths, Capistrano kept searching on my local machine and throwing errors when it couldn't find those paths.
What I had to do was add the local_repository to the config and then everything worked. So the bits I changed are these:
set :local_repository, '~/Dropbox/app_name/.git'
set :repository, '~/railsApps/app_name.git'
set :deploy_to, '~/railsApps/app_name'
The local_repository path is local to my machine and the repository and deploy_to paths are local to the remote server.
First of all: Capistrano always executes it's commands on the remote server you are deploying to.
This means that all paths you use like in set :deploy_to are local paths on the server.
In my case the config looks something like this:
set :scm, 'git'
set :repository, "<repo url>"
set :branch, 'master'
set :git_shallow_clone, 1
set :scm_verbose, true
set :deploy_to, '/var/www/app'
set :deploy_via, :remote_cache
The important part here is the :deploy_to that is a local path on the server not a SSH path. This is where your config is wrong!
This gets even more important if you look at the commands capistrano then runs. It for example will usually do things like bash cd /var/www/app && bundle instal ....
If the path is not local the command will most likely fail.
Secondly this also means that Capistrano will deploy to your Git Server from your Remote Server, so you have to make sure the remote server has access to the Git Server.
The ssh_options[:keys] therefore specifies the local SSH key used to connect to that remote_server, while on the server the default key from ~/.ssh/id_rsa.pub will be used.
You can avoid having to set up your SSH key on the Server by using SSH Agent forwarding by including ssh_options[:forward_agent] = true. This will simply forward your local SSH agent socket to the server and use that (good because your key never leaves your machine)
More info on SSH Agent forwarding can be found here
Thins to check:
Check in the remote server for .ssh folder and make sure your ssh key(id_rsa.pub) is added to authorized keys with no space appended.
do ssh-add from you local folder from where you are running the cap script.
Check for the permissions of .ssh folder on remote, it should be 700 and files inside with 600 permission.
If I change the Capistrano configuration to clone from the remote git folder to which I push (which is in that same server) then I don't get an error but it asks for my password every time I try to connect.
Now clone it from the git,

capistrano deploy asking for USERNAME / PASSWORD on git ls-remote call

First time Capistrano user, I have set up the pieces from the best I can tell but when I run cap deploy, I get the following asking for my github username
Fri Dec 02$ cap deploy
* executing `deploy'
* executing `deploy:update'
** transaction: start
* executing `deploy:update_code'
executing locally: "git ls-remote https://github.com/uname/repo HEAD"
Username:
I'm assuming that this running locally on my OS X laptop. If I run git ls-remote https://github.com/uname/repo, I get prompted for a USERNAME. However, I can run git clone this repository fine, making me think that the local ssh keys are set up correctly. What am I missing here?
thx
edit #1 - top of deploy.rb
set :application, "test-rails"
set :repository, "https://github.com/uname/app"
set :scm, :git
set :user, "deploy"
set :deploy_to, "/data/sites/site.com/apps/#{application}"
set :use_sudo, false
set :keep_releases, 5
role :web, "173.230.xxx.xxx"
You're using an HTTPS URL. This will ignore your SSH keys, and you'll have to do basic authentication over HTTPS. You want your URL to instead be ssh://git#github.com/uname/repo.
(Cloning works because you can clone anonymously and don't need to authenticate.)
perhaps it will help to others:
on target server make sure credentials for cached repo.
t cached my first NON password url and no matter how i update url in deploy.rb it was not updated on origin
in my case...
go to:
/srv/YOURREPONAME/shared/cached-copy
git remote show origin
make sure your origin has same URL as you trying to set in deploy.rb

newbie capistrano rails deployment problem (can't find git in the path)

I'm using: Rails 3, ruby 1.9.2 and trying to deploy using capistrano. When I run cap deploy:check, capistrano tells me that it can't find git on my deployment server (see below).
Any thoughts on what I'm doing wrong??
Here's my setup.
I have a git repo # github
I have a
laptop with an updated local copy of
the github repo
I have a local
"production" server (192.168.0.103) where the
production app should be deployed
I'm running all commands from the local repo on my laptop (not the production server)
If I run cap deploy:setup, my deploy.rb file successfully adds the "releases" and "shared" directories on my production server (aka 192.168.0.103).
If I run the cap deploy:check command, it fails with the error message of
`git' could not be found in the path (192.168.0.103).
What is strange (to me at least) is that git is definitely installed on 192.168.0.103 and the command that's used to see if git is there (which git) works when I ssh into 192.168.0.103.
So, obviously I'm doing something wrong (maybe in the deploy.rb file?)
Here's a sanitized version of the deploy.rb file
default_run_options[:pty] = true
set :application, "myapp"
set :repository, "git#github.com:xxxxxxx/myapp.git"
set :user, "abcde" #username that's used to ssh into 192.168.0.103
set :scm, :git
set :scm_passphrase, "xxxxxxxx"
set :branch, "master"
set :deploy_via, :remote_cache
set :deploy_to, "/Users/abcde/www"
role :web, "192.168.0.103"
role :app, "192.168.0.103"
Here's the output of cap deploy:check
* executing `deploy:check'
* executing "test -d /Users/abcde/www/releases"
servers: ["192.168.0.103"]
Password:
[192.168.0.103] executing command
command finished
* executing "test -w /Users/abcde/www"
servers: ["192.168.0.103"]
[192.168.0.103] executing command
command finished
* executing "test -w /Users/abcde/www/releases"
servers: ["192.168.0.103"]
[192.168.0.103] executing command
command finished
* executing "which git"
servers: ["192.168.0.103"]
[192.168.0.103] executing command
command finished
The following dependencies failed. Please check them and try again:
--> `git' could not be found in the path (192.168.0.103)
Okay, I think I figured it out.
I was basically having the same problem as described here: http://groups.google.com/group/capistrano/browse_thread/thread/50af1daed0b7a393
Here's a choice excerpt:
I try to deploy an application on a
shared environment on which I
installed git. I have added the path
to bashrc, but this would work only
in an interactive bash. When cap is
logging in, it will not be running
bash. If I run deploy:check it fails
by
--> `git' could not be found in the path (example.com) If i set
:scm_command, "/home/user/opt/bin/git"
the problem is solved with the
deploy:check command, but when I run
deploy:cold, it fails because it
tries to run /home/user/opt/bin/git
locally and I can't even put git in
there, because I use windows on my pc.
adding :scm_command, "path/to/my/git" fixed the issue, although I'm not 100% that this is the correct approach to take.
I would recommend using:
default_run_options[:env] = {'PATH' => '/home/user/opt/bin/git:$PATH'}
This will allow adjusting the PATH system environment variable (and of them more if needed) so that not only the "Capistrano can't find the SCM" problem get solved bu any other similar problems with Capistrano not running in interactive bash (not executing the .bashrc etc.).

Resources