如何将自己的 public 密钥添加到 Vagrant VM?

How do I add my own public key to Vagrant VM?

我在向 Vagrant VM 添加 ssh 密钥时遇到问题。基本上我在这里的设置工作正常。创建 VM 后,我可以通过 vagrant ssh 访问它们,用户 "vagrant" 存在并且 authorized_keys 文件中有该用户的 ssh 密钥。

我现在想做的是:能够通过 ssh 或使用 scp 连接到这些虚拟机。所以我只需要将我的 public 键从 id_rsa.pub 添加到 authorized_keys - 就像我对 ssh-copy-id 所做的那样。

有没有办法在设置过程中告诉 Vagrant 我的 public 密钥应该包括在内?如果不是(根据我的 google 结果,这很可能),有没有办法在 vagrant 设置期间轻松附加我的 public 密钥?

复制所需的 public 密钥将直接进入 provisioning 阶段。确切的答案取决于您喜欢使用什么配置(shell、Chef、Puppet 等)。最微不足道的是密钥的 file 供应商,如下所示:

config.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/me.pub"

嗯,实际上你需要追加到 authorized_keys。使用 shell 配置器,像这样:

Vagrant.configure(2) do |config|
  # ... other config
  config.vm.provision "shell", inline: <<-SHELL
    cat /home/vagrant/.ssh/me.pub >> /home/vagrant/.ssh/authorized_keys
  SHELL
  # ... other config
end

您也可以使用真正的配置器,例如 Puppet. For example see Managing SSH Authorized Keys with Puppet

你可以使用Ruby的核心文件模块,像这样:

  config.vm.provision "shell" do |s|
    ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
    s.inline = <<-SHELL
      echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
      echo #{ssh_pub_key} >> /root/.ssh/authorized_keys
    SHELL
  end

此工作示例将 ~/.ssh/id_rsa.pub 附加到 vagrant 和 root 用户的 ~/.ssh/authorized_keys,这将允许您使用现有的 SSH 密钥。

还有一种 "elegant" 方法可以完成您想做的事情。您可以找到现有的私钥并使用它,而不是经历添加 public 密钥的麻烦。

像这样继续查看现有私钥的路径(在下面查找 IdentityFile):

运行

 vagrant ssh-config 

结果:

$ vagrant ssh-config
Host magento2.vagrant150
  HostName 127.0.0.1
  User vagrant
  Port 3150
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile "/Users/madismanni/m2/vagrant-magento/.vagrant/machines/magento2.vagrant150/virtualbox/private_key"
  IdentitiesOnly yes
  LogLevel FATAL

然后就可以这样使用私钥了,还要注意关闭密码认证的开关

ssh -i /Users/madismanni/m2/vagrant-magento/.vagrant/machines/magento2.vagrant150/virtualbox/private_key -o PasswordAuthentication=no vagrant@127.0.0.1 -p 3150

更短更正确的代码应该是:

ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
config.vm.provision 'shell', inline: 'mkdir -p /root/.ssh'
config.vm.provision 'shell', inline: "echo #{ssh_pub_key} >> /root/.ssh/authorized_keys"
config.vm.provision 'shell', inline: "echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys", privileged: false

否则用户的.ssh/authorized_keys将属于root用户。

还是会在每个provision处加一行运行,但是Vagrant是用来测试的,VM一般寿命很短,所以问题不大。

我最终使用的代码如下:

config.ssh.forward_agent    = true
config.ssh.insert_key       = false
config.ssh.private_key_path =  ["~/.vagrant.d/insecure_private_key","~/.ssh/id_rsa"]
config.vm.provision :shell, privileged: false do |s|
  ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
  s.inline = <<-SHELL
     echo #{ssh_pub_key} >> /home/$USER/.ssh/authorized_keys
     sudo bash -c "echo #{ssh_pub_key} >> /root/.ssh/authorized_keys"
  SHELL
end

请注意,我们不应该对 /home/vagrant/.ssh/authorized_keys 的路径进行硬编码,因为一些 vagrant boxes 不使用 vagrant 用户名。

这是一个很好的话题,它帮助我解决了与原始发帖者描述的类似情况。

虽然我最终使用 answer, I ran into a hitch since I use the VAGRANT_HOME 环境变量中的 settings/logic 将核心 vagrant.d 目录内容保存在我的一个开发系统的外部硬盘驱动器上。

所以这是我在 Vagrantfile 中使用的调整代码,以适应设置的 VAGRANT_HOME 环境变量; “魔法”发生在这一行 vagrant_home_path = ENV["VAGRANT_HOME"] ||= "~/.vagrant.d":

config.ssh.insert_key = false
config.ssh.forward_agent = true
vagrant_home_path = ENV["VAGRANT_HOME"] ||= "~/.vagrant.d"
config.ssh.private_key_path = ["#{vagrant_home_path}/insecure_private_key", "~/.ssh/id_rsa"]
config.vm.provision :shell, privileged: false do |shell_action|
  ssh_public_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
  shell_action.inline = <<-SHELL
    echo #{ssh_public_key} >> /home/$USER/.ssh/authorized_keys
  SHELL
end

生成用于 vagrant 身份验证的 rsa 密钥对ssh-keygen -f ~/.ssh/vagrant

您可能还想将 vagrant 身份文件添加到您的 ~/.ssh/config

IdentityFile ~/.ssh/vagrant
IdentityFile ~/.vagrant.d/insecure_private_key

出于某种原因,我们不能只指定要插入的密钥,因此我们采用 自己生成密钥的几个额外步骤。这样我们得到安全和 确切知道我们需要哪个密钥(+所有 vagrant boxes 将获得相同的密钥)

config.ssh.insert_key = false
config.ssh.private_key_path = ['~/.ssh/vagrant', '~/.vagrant.d/insecure_private_key']
config.vm.provision "file", source: "~/.ssh/vagrant.pub", destination: "/home/vagrant/.ssh/vagrant.pub"
config.vm.provision "shell", inline: <<-SHELL
cat /home/vagrant/.ssh/vagrant.pub >> /home/vagrant/.ssh/authorized_keys
mkdir -p /root/.ssh
cat /home/vagrant/.ssh/authorized_keys >> /root/.ssh/authorized_keys

SHELL

对于内联 shell 配置器 - public 键通常包含空格、注释等。因此请确保在扩展为public 键:

config.vm.provision 'shell', inline: "echo \"#{ssh_pub_key}\" >> /home/vagrant/.ssh/authorized_keys", privileged: false

这个出色的答案是由 user76329 in a rejected Suggested Edit

添加的

扩展,我们可以复制本地pub/private ssh密钥,设置权限,并使内联脚本幂等(运行一次,仅在测试条件失败时重复,因此需要配置):

config.vm.provision "shell" do |s|
  ssh_prv_key = ""
  ssh_pub_key = ""
  if File.file?("#{Dir.home}/.ssh/id_rsa")
    ssh_prv_key = File.read("#{Dir.home}/.ssh/id_rsa")
    ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
  else
    puts "No SSH key found. You will need to remedy this before pushing to the repository."
  end
  s.inline = <<-SHELL
    if grep -sq "#{ssh_pub_key}" /home/vagrant/.ssh/authorized_keys; then
      echo "SSH keys already provisioned."
      exit 0;
    fi
    echo "SSH key provisioning."
    mkdir -p /home/vagrant/.ssh/
    touch /home/vagrant/.ssh/authorized_keys
    echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
    echo #{ssh_pub_key} > /home/vagrant/.ssh/id_rsa.pub
    chmod 644 /home/vagrant/.ssh/id_rsa.pub
    echo "#{ssh_prv_key}" > /home/vagrant/.ssh/id_rsa
    chmod 600 /home/vagrant/.ssh/id_rsa
    chown -R vagrant:vagrant /home/vagrant
    exit 0
  SHELL
end

None 中较旧的 post 对我有用,尽管有些接近。我必须在终端中使用 keygen 制作 rsa 密钥并使用自定义密钥。换句话说,因使用 Vagrant 的钥匙而被打败。

我在 Mac OS 莫哈韦沙漠post。我在一个 Vagrantfile 中设置了两个 Vagrant 盒子。我展示了第一个框的所有内容,以便新手可以看到上下文。我将 .ssh 文件夹放在与 Vagrant 文件相同的文件夹中,否则使用 user9091383 设置。

此解决方案归功于 this coder.

Vagrant.configure("2") do |config|
  config.vm.define "pfbox", primary: true do |pfbox|
        pfbox.vm.box = "ubuntu/xenial64"
        pfbox.vm.network "forwarded_port", host: 8084, guest: 80
        pfbox.vm.network "forwarded_port", host: 8080, guest: 8080
        pfbox.vm.network "forwarded_port", host: 8079, guest: 8079
        pfbox.vm.network "forwarded_port", host: 3000, guest: 3000
        pfbox.vm.provision :shell, path: ".provision/bootstrap.sh"
        pfbox.vm.synced_folder "ubuntu", "/home/vagrant"
        pfbox.vm.provision "file", source: "~/.gitconfig", destination: "~/.gitconfig"
        pfbox.vm.network "private_network", type: "dhcp"
        pfbox.vm.network "public_network"
        pfbox.ssh.insert_key = false
        ssh_key_path = ".ssh/"  # This may not be necessary.  I may remove.
        pfbox.vm.provision "shell", inline: "mkdir -p /home/vagrant/.ssh"
        pfbox.ssh.private_key_path = ["~/.vagrant.d/insecure_private_key", ".ssh/id_rsa"]
        pfbox.vm.provision "file", source: ".ssh/id_rsa.pub", destination: ".ssh/authorized_keys"
        pfbox.vm.box_check_update = "true"
        pfbox.vm.hostname = "pfbox"
        # VirtualBox
          config.vm.provider "virtualbox" do |vb|
            # vb.gui = true
            vb.name = "pfbox" # friendly name for Oracle VM VirtualBox Manager
            vb.memory = 2048 # memory in megabytes 2.0 GB
            vb.cpus = 1 # cpu cores, can't be more than the host actually has.
          end
  end
  config.vm.define "dbbox" do |dbbox|
        ...

Madis Maenni 的答案最接近最佳解决方案:

就这样:

vagrant ssh-config >> ~/.ssh/config
chmod 600 ~/.ssh/config

然后你就可以通过主机名 ssh 了。

获取在 ~/.ssh/config

中配置的主机名列表
grep -E '^Host ' ~/.ssh/config

我的例子:

$ grep -E '^Host' ~/.ssh/config
Host web
Host db
$ ssh web
[vagrant@web ~]$

一个很完整的例子,希望对下一个访问的人有所帮助。将所有具体值移至外部配置文件。 IP分配只是为了试用。

# -*- mode: ruby -*-
# vi: set ft=ruby :

require 'yaml'
vmconfig = YAML.load_file('vmconfig.yml')

=begin
Script to created VMs with public IPs, VM creation governed by the provided
config file.
All Vagrant configuration is done below. The "2" in Vagrant.configure
configures the configuration version (we support older styles for
backwards compatibility). Please don't change it unless you know what
you're doing
Default user `vagrant` is created and ssh key is overridden. make sure to have
the files `vagrant_rsa` (private key) and `vagrant_rsa.pub` (public key) in the
path `./.ssh/`
Same files need to be available for all the users you want to create in each of
these VMs
=end

uid_start = vmconfig['uid_start']
ip_start = vmconfig['ip_start']
vagrant_private_key = Dir.pwd + '/.ssh/vagrant_rsa'
guest_sshkeys = '/' + Dir.pwd.split('/')[-1] + '/.ssh/'
Vagrant.configure('2') do |config|
  vmconfig['machines'].each do |machine|
    config.vm.define "#{machine}" do |node|
      ip_start += 1
      node.vm.box = vmconfig['vm_box_name']
      node.vm.box_version = vmconfig['vm_box_version']
      node.vm.box_check_update = false
      node.vm.boot_timeout = vmconfig['vm_boot_timeout']
      node.vm.hostname = "#{machine}"
      node.vm.network "public_network", bridge: "#{vmconfig['bridge_name']}", auto_config: false
      node.vm.provision "shell", run: "always", inline: "ifconfig #{vmconfig['ethernet_device']} #{vmconfig['public_ip_part']}#{ip_start} netmask #{vmconfig['subnet_mask']} up"
      node.ssh.insert_key = false
      node.ssh.private_key_path = ['~/.vagrant.d/insecure_private_key', "#{vagrant_private_key}"]
      node.vm.provision "file", source: "#{vagrant_private_key}.pub", destination: "~/.ssh/authorized_keys"
      node.vm.provision "shell", inline: <<-EOC
        sudo sed -i -e "\#PasswordAuthentication yes# s#PasswordAuthentication yes#PasswordAuthentication no#g" /etc/ssh/sshd_config
        sudo systemctl restart sshd.service
      EOC
      vmconfig['users'].each do |user|
        uid_start += 1
        node.vm.provision "shell", run: "once", privileged: true, inline: <<-CREATEUSER
          sudo useradd -m -s /bin/bash -U #{user} -u #{uid_start}
          sudo mkdir /home/#{user}/.ssh
          sudo cp #{guest_sshkeys}#{user}_rsa.pub /home/#{user}/.ssh/authorized_keys
          sudo chown -R #{user}:#{user} /home/#{user}
          sudo su
          echo "%#{user} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/#{user}
          exit
        CREATEUSER
      end
    end
  end