Question

I've narrowed down this question - regarding a MySQL over SSH connection only working once - to a conflicting line in my host computer's known_hosts file.

Essentially, I can not get into my Database GUI of choice because the key is different for the same IP address (after re-provisioning, reloading, etc.).

Once I delete any offending lines, I can get in just fine.

So, through Vagrant's shell command (that I'm provisioning with) how can I modify the host machine's ~/.ssh/known_hosts file?

EDIT: I found a temp fix that involves adding/creating a ~/.ssh/config file (this involves using a private IP address):

Host 192.168.*.*
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

Should let you in. Not a real fix, as this kind of fix can be a security concern. Look below for much better answer.

Was it helpful?

Solution

Sorry for taking you away from what you need!

Changing HOST files from Vagrantfile:

What you actually want is very simple. Vagrantfile is interpreted by Vagrant each time you run vagrant command. It is regular ruby code, so if you want to change HOST file, all you need to do is to put in the Vagrantfile Ruby code that performs this change. Here's the example code I've put at the end of my Vagrantfile:

require 'tempfile' 
require 'fileutils'  

path = '~/.ssh/known_hosts' 
temp_file = Tempfile.new('foo') 
begin   
  File.open(path, 'r') do |file|
    file.each_line do |line|
      if line !~ /REGEX_OF_LINE_YOU_WANT_TO_EXCLUDE/ then
        temp_file.puts line
      end
    end
  end   
  temp_file.rewind   
  FileUtils.mv(temp_file.path, path) 
  ensure   
    temp_file.close
    temp_file.unlink
  end

Note to edit the code above by putting your own value for REGEX_OF_LINE_YOU_WANT_TO_EXCLUDE.

Hope I at least partially fixed my mistake by providing this answer :)


Original Answer

For anyone's (mine as well) future reference, I'm leaving part of the answer that refers to changing GUEST OS files or copying files to GUEST OS:

Vagrant provides couple of provisioners.

Solution number 1: For simple file copy you may use Vagrant file provisioner. Following code in your Vagrantfile would copy the file ~/known_hosts.template from your host system to VM's file /home/vagrant/.ssh/known_hosts

# Context -------------------------------------------------------
Vagrant.configure('2') do |config|
  # ...

  # This is the section to add ----------------------------------
  config.vm.provision :file do |file|
    file.source      = '~/known_hosts.template'
    file.destination = '/home/vagrant/.ssh/known_hosts'
  end
  #--------------------------------------------------------------
end

File provisioner is poorly documented on Vagrant site, and we've got to thank @tmatilai who had answered similar question on serverfault.

Keep in mind that you should use absolute paths in destination field, and that copying is being performed by vagrant user, so file will have vagrant's owner:group.

Solution number 2: If you need to copy file with a root privileges, or really have to change the file without using templates, consider using well documented shell provisioner. File copying in this case would work only if you have the file placed in the folder visible from within the VM(guestOS), but you have all the power of shell.

Solution number 3: Though it would be overkill in this case, you might use very powerful Chef or Puppet as provisioners, and perform action via one of those frameworks. I know nothing about Puppet, and may talk only about Chef. Cookbook would be very simple. Create template file (.erb) with desired content, and then your recipe will just place the file where necessary. Of course you'll need a box with Chef packeges in it.

OTHER TIPS

I use plain ssh to enter my machines in order to do provisioning:

$ ssh-add ~/.vagrant.d/insecure_private_key

With this setup the known hosts is bound to give problems, but I do not want to turn off the host key checking as I use that also for external hosts. Given my hosts include pattern foo, I did this on the shell:

$ ssh -i '' '/foo/d' ~/.ssh/known_hosts

Remove the empty '' argument after -i if you have GNU/linux host in stead of BSD/MacOSX.

You can then install the vagrant trigger plugin:

$ vagrant plugin install vagrant-triggers

And add the above snippet to the Vagrantfile (mind the backticks):

config.trigger.after :destroy do
   puts "Removing known host entries"
   `sed -i '' '/foo/d' ~/.ssh/known_hosts`
end

This is what I do:

I define the IP_ADDRESS and DOMAIN_NAME variables at the top of the Vagrantfile.

Then inside Vagrant.configure I add:

config.trigger.after :destroy do |trigger|
  trigger.info = "Removing known_hosts entries"
  trigger.run = {inline: "ssh-keygen -R #{IP_ADDRESS}"}
  trigger.run = {inline: "ssh-keygen -R #{DOMAIN_NAME}"}
end 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top