I'm trying to make our dev onboarding process as seamless as possible.
Part of the functionality we want in the VM is to have our code pulled in from github onto the VM.
In my Vagrantfile I added the private_key and forward_agent options like so:
config.ssh.private_key_path = "~/.ssh/id_rsa"
config.ssh.forward_agent = true
However, when I do a vagrant up
I get this:
SSH authentication failed! This is typically caused by the public/private
keypair for the SSH user not being properly set on the guest VM. Please
verify that the guest VM is setup with the proper public key, and that
the private key path for Vagrant is setup properly as well.
To fix this, I SSH (with vagrant as the password), and I append my public key to ~/.ssh/authorized_keys
I'm also using the puppet provisioner.
I've found a hacky workaround using sed, but is there a way for vagrant to automatically add my public key to the authorized keys?
@krashidov The answer to your question is in the docs at http://vagrantup.com/v1/docs/base_boxes.html:
Since Vagrant only supports key-based authentication for SSH, you must setup the SSH user to use key-based authentication. This simply requires copying a public key into ~/.ssh/authorized_keys.
You need to do this regardless of whether you are using the public, and therefore insecure keys, or a set of private keys for your own personal use. Thus, you will need to repackage the Base Box with your public key in the authorized_keys file.
@krashidov Are you still using that hacky workaround?
I would also love to see some sort of automation that does this. Say you have many developers. Each of them has their own SSH key that they forward into vagrant which controls their authorization (some have push access, some have pull access, while some have deploy access). Since vagrant's motto is being able to tear down boxes quickly and bring them back up seamlessly, having to manually copy your public key to authorized_keys goes against this and adds unnecessary friction. But being able to define something in each user's local Vagrantfile such as
config.ssh.public_key_path = "~/.ssh/id_rsa.pub"
would allow developers to mindlessly bring up vagrant boxes from various projects and still be able to use their own SSH key.
Maybe I will get around to this someday, but this would probably make for a good vagrant plugin. In the meantime, you can probably use the shell provisioner to accomplish this.
I have the exact situation that @axsuul describes, with multiple developers who would ideally each put his/her own SSH key into his/her own Vagrant box. A configuration setting to specify a public key (or multiple public keys) for the authorized_keys file would be great. I am happy to work on this but would probably need some pointers since I'm unfamiliar with the Vagrant codebase. Let me know if you can help.
:+1:
There is a chicken/egg problem here, because Vagrant needs to be able to SSH in to bootstrap users, and it can't SSH in if it doesn't already have a key. I'd love to be able to bootstrap new SSH keys for every vagrant up but it doesn't look like there is proper support for that in upstream things right now.
One option is actually to use VirtualBox's copy file into guest features and such but those have been horribly unstable for me.
I like the look of #907 instead.
@mitchellh I actually hacked up something similar to what is wanted here for a large Vagrant setup at my work. I basically appended the SSH keys to authorized_keys in addition to the existing key that Vagrant was using using a shell provisioner to copy a configured SSH key into the box on creation. I think @axsuul is right in that this is something a plugin should be written for, rather than it being in core Vagrant.
Let me just add a "me too" to this list. We use vagrant to setup devboxes, and getting the ssh access to work correctly (especially when paired with Jenkins) is mind-numbing.
you can do this with something like that:
id_rsa_ssh_key = File.read(File.join(Dir.home, ".ssh", "id_rsa"))
id_rsa_ssh_key_pub = File.read(File.join(Dir.home, ".ssh", "id_rsa.pub"))
config.vm.provision :shell, :inline => "echo 'Windows-specific: Copying local Stash SSH Key to VM for provisioning...' && mkdir -p /home/vagrant/.ssh && echo '#{stash_ssh_key}' > /home/vagrant/.ssh/stash_rsa && chmod 600 /home/vagrant/.ssh/stash_rsa && echo '#{stash_ssh_key}' > /home/vagrant/.ssh/authorized_keys && chmod 600 /home/vagrant/.ssh/stash_rsa"
config.vm.provision :shell, :inline => "echo 'Windows-specific: Copying local id_rsa SSH Key to VM for git and auth purposes (login included)...' && echo '#{id_rsa_ssh_key }' > /home/vagrant/.ssh/id_rsa && chmod 600 /home/vagrant/.ssh/id_rsa"
config.vm.provision :shell, :inline => "echo 'Windows-specific: Copying local id_rsa SSH Key to VM auth_keys for auth purposes (login into VM included)...' && echo '#{id_rsa_ssh_key_pub }' > /home/vagrant/.ssh/authorized_keys && chmod 600 /home/vagrant/.ssh/authorized_keys"
that's quite amazing than 2 years later there is still no easy option to add a user public key...
^ what he said. BOO.
thank you @programadoresweb for code snippet! sorted out the issue with cloning private github repo for me
Is there still no easy way to add a public key??
eh whatever I found it easier to just use ssh forwarding or whatever.
Building on the example from @alex-moreno, this provisioning script will replace the default insecure key with your custom ssh key. Vagrant is configured to use both keys, so it will use the insecure key to provision the first time, then use your private key going forward.
private_key_path = File.join(Dir.home, ".ssh", "id_rsa")
public_key_path = File.join(Dir.home, ".ssh", "id_rsa.pub")
insecure_key_path = File.join(Dir.home, ".vagrant.d", "insecure_private_key")
private_key = IO.read(private_key_path)
public_key = IO.read(public_key_path)
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty64"
config.ssh.insert_key = false
config.ssh.private_key_path = [
private_key_path,
insecure_key_path # to provision the first time
]
config.vm.provision :shell, :inline => <<-SCRIPT
set -e
echo '#{private_key}' > /home/vagrant/.ssh/id_rsa
chmod 600 /home/vagrant/.ssh/id_rsa
echo '#{public_key}' > /home/vagrant/.ssh/authorized_keys
chmod 600 /home/vagrant/.ssh/authorized_keys
SCRIPT
end
That script didn't work for me. I've been trying to parse through the code to figure out how the keys and password get set up and it would be nice if there were a more straightforward way to set up the authentication with a specified set of keys.
The entire .ssh directory gets overwritten when the public key is inserted, overwriting any provisioned keys if the insecure_key is included in the private_key path and there's no password.
If you set a password, then keys aren't used at all.
If you don't set a password, then the default of 'vagrant' remains, which defeats the intent of only being able to get in with a specified key pair, but it does prevent the insertion of a newly generated set of keys (and overwriting of the guest .ssh directory).
I tried this
config.vm.provision "file", source: "~/.vagrant.d/vagrant_private_key.pub", destination: "~/.ssh/authorized_keys"
config.ssh.private_key_path = ["~/.vagrant.d/vagrant_private_key", "~/.vagrant.d/insecure_private_key"]
config.ssh.password = nil
config.ssh.insert_key = false
and then do a vagrant ssh and the password prompt comes up, for which "vagrant" works and the .ssh directory has been overwritten with authorized_keys.
Do you pretty much have to get into the box after it's running to make it secure?
I'm relatively new to Vagrant and provisioning in general, so may be missing something basic or not aware of other tools that get this done, but from a new person's perspective, it would be much more straightforward if the options were as follows:
And don't overwrite the entire .ssh directory so it's possible to provision other keys in there.
I wanted to allow either the vagrant created key or the user's key. Thanks to the examples above, I was able to use this.
# SSH Key Access
public_key_path = File.join(Dir.home, ".ssh", "id_rsa.pub")
if File.exist?(public_key_path)
public_key = IO.read(public_key_path)
end
config.ssh.forward_agent = true
config.ssh.keys_only = false
# Disables the vagrant generated key.
# Uncomment if you only want access via user's key.
#config.ssh.insert_key = false
config.vm.provision :shell, :inline => <<-SCRIPT
set -e
# Add host user's ssh public key to authorized_hosts
homedir=$(getent passwd "$SUDO_USER" | cut -d: -f6)
echo '#{public_key}' >> $homedir/.ssh/authorized_keys
chmod 600 $homedir/.ssh/authorized_keys
SCRIPT
@sr105 what would I do if I"m on a Win10 host? My keys are on an SD Chip.
Can't you change the public_key_path to pint to your public key file?
@sr105 It think I would use /d/ssh to represent drive d:. I'll test that.
In case you've come to find out how to do this,
Mac & Vagrant
Vagrant.configure('2') do |config|
config.vm.box = 'ubuntu/xenial64' # 16.04
config.vm.hostname = 'mybox'
config.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
config.ssh.forward_agent = true
config.ssh.keys_only = false
# Disables the vagrant generated key.
# Uncomment if you only want access via user's key.
config.ssh.insert_key = false
end
@CalebEverett I added this configuration and it worked. Thank you!
Vagrant.configure("2") do |config|
config.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/authorized_keys"
config.ssh.private_key_path = ["~/.vagrant.d/insecure_private_key", "~/.ssh/id_rsa"]
config.ssh.insert_key = false
end
Another way is to append a specific set of public keys into the guest authorized_keys.
# Copy local public key(s) to guest
config.vm.provision "file", source: "./import_keys.pub", destination: "/home/vagrant/.ssh/import_keys.pub"
# append import key(s) to authorized_keys and remove duplicates
$script = <<-SCRIPT
cd /home/vagrant/.ssh
cat import_keys.pub >> authorized_keys
sort authorized_keys | uniq > public_keys.pub
mv public_keys.pub authorized_keys
rm *.pub
SCRIPT
config.vm.provision "shell" do |sh|
sh.inline = $script
sh.privileged = false
end
Note that duplicates are removed for faux idempotence on repeated provisions.
I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
Building on the example from @alex-moreno, this provisioning script will replace the default insecure key with your custom ssh key. Vagrant is configured to use both keys, so it will use the insecure key to provision the first time, then use your private key going forward.