Mark Needham

Thoughts on Software Development

Capistrano: Host key verification failed. ** [err] fatal: The remote end hung up unexpectedly

with 3 comments

As I mentioned in my previous post I’ve been deploying a web application to a vagrant VM using Capistrano and my initial configuration was like so:

require 'capistrano/ext/multistage'
 
set :application, "thinkingingraphs"
set :scm, :git
set :repository,  "git@bitbucket.org:markhneedham/thinkingingraphs.git"
set :scm_passphrase, ""
 
set :ssh_options, {:forward_agent => true, :paranoid => false, keys: ['~/.vagrant.d/insecure_private_key']}
set :stages, ["vagrant"]
set :default_stage, "vagrant"
 
set :user, "vagrant"
server "192.168.33.101", :app, :web, :db, :primary => true
set :deploy_to, "/var/www/thinkingingraphs"

When I ran ‘cap deploy’ I ended up with the following error:

  * executing "git clone -q git@bitbucket.org:markhneedham/thinkingingraphs.git /var/www/thinkingingraphs/releases/20130414171523 && cd /var/www/thinkingingraphs/releases/20130414171523 && git checkout -q -b deploy 6dcbf945ef5b8a5d5d39784800f4a6b7731c7d8a && (echo 6dcbf945ef5b8a5d5d39784800f4a6b7731c7d8a > /var/www/thinkingingraphs/releases/20130414171523/REVISION)"
    servers: ["192.168.33.101"]
    [192.168.33.101] executing command
 ** [192.168.33.101 :: err] Host key verification failed.
 ** [192.168.33.101 :: err] fatal: The remote end hung up unexpectedly

As far as I can tell the reason for this is that bitbucket hasn’t been verified as a host by the VM and therefore the equivalent of the following happens when it tries to clone the repository:

$ ssh git@bitbucket.org
The authenticity of host 'bitbucket.org (207.223.240.182)' can't be established.
RSA key fingerprint is 97:8c:1b:f2:6f:14:6b:5c:3b:ec:aa:46:46:74:7c:40.
Are you sure you want to continue connecting (yes/no)?

Since we aren’t answering ‘yes’ to that question and bitbucket isn’t in our ~/.ssh/known_hosts file it’s not able to continue.

One solution to this problem is to run the ssh command above and then answer ‘yes’ to the question which will add bitbucket to our known_hosts file and we can then run ‘cap deploy’ again.

It’s a bit annoying to have that manual step though so another way is to set cap to use pty by putting the following line in our config file:

set :default_run_options, {:pty => true}

Now when we run ‘cap deploy’ we can see that bitbucket automatically gets added to the known_hosts file:

    servers: ["192.168.33.101"]
    [192.168.33.101] executing command
 ** [192.168.33.101 :: out] The authenticity of host 'bitbucket.org (207.223.240.181)' can't be established.
 ** RSA key fingerprint is 97:8c:1b:f2:6f:14:6b:5c:3b:ec:aa:46:46:74:7c:40.
 ** Are you sure you want to continue connecting (yes/no)?
 ** [192.168.33.101 :: out] yes
 ** [192.168.33.101 :: out] Warning: Permanently added 'bitbucket.org,207.223.240.181' (RSA) to the list of known hosts.

As far as I can tell this runs the command using a pseudo terminal and then automatically adds bitbucket into the known_hosts file but I’m not entirely sure how that works. My google skillz have also failed me so if anyone can explain it to me that’d be cool

Be Sociable, Share!

Written by Mark Needham

April 14th, 2013 at 6:18 pm

Posted in DevOps

Tagged with

  • OpenSSH has a `StrictHostKeyChecking` option which controls the behaviour when connecting to unknown hosts. You can always add unknown hosts automatically (`yes), never add automatically (`no`), or try asking whether to trust a new host (`ask`). The default on most systems is `ask`. (See `man 5 ssh_config` for details.)

    When a well-behaved Unix program needs to interact with a user — such as asking a question, taking a password, or using color codes designed for screens — the Unix program will first check whether it is connected to an interactive terminal. For example, look at what the `less` pager does when it’s not at the end of a pipeline: `fortune | less | head`. When `less` runs, its stdout is a pipe (the same pipe that `head` gets as stdin). `less` notices that this particular stdout is not a terminal, so skips the interactive behaviour (and works like `cat`). OpenSSH works the same way.

    When you ask Capistrano to allocate a pseudo-terminal, then the pipe that `cap` gives to subprocesses as stdin and stdout responds positively to `isatty()`. The end result? Programs like `less` and OpenSSH act as if they are connected to a terminal — because they are!

    I hope this helps.

  • Mark Needham

    Ah neat, so that last bit ties in with what Ian suggested on twitter – https://twitter.com/cartwrightian/status/323774764361609216

    “@markhneedham my guess: perhaps the code is checking if a tty is attached? http://www.linuxjournal.com/content/determine-if-shell-input-coming-terminal-or-pipe

  • This article is quite interesting for explaining how tty’s came into being and runs through a few examples which are quite neat – http://www.linusakesson.net/programming/tty/index.php