How to Properly Transfer SSH Deploy Keys to Vagrant Without Overwriting the .ssh Directory


11 views

Many developers encounter this issue when trying to provision SSH keys in Vagrant environments. The key observation here is that Vagrant automatically manages the ~/.ssh directory during vagrant up, which can override manually placed keys.

When examining your current Vagrantfile approach:

config.vm.provision :shell, 
:inline => "cp /svr/conf.d/.ssh/id_rsa.mediapop /home/ubuntu/.ssh/id_rsa"

The issue occurs because:

  • Vagrant resets the SSH configuration during provisioning
  • File permissions may be incorrect (notice root ownership in your output)
  • The home directory path differs between provisioning and SSH sessions

Here's a robust method that works with Vagrant's lifecycle:

config.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "/tmp/id_rsa.pub"
config.vm.provision "shell", inline: <<-SHELL
  mkdir -p /home/vagrant/.ssh
  cat /tmp/id_rsa.pub >> /home/vagrant/.ssh/authorized_keys
  chown -R vagrant:vagrant /home/vagrant/.ssh
  chmod 700 /home/vagrant/.ssh
  chmod 600 /home/vagrant/.ssh/*
SHELL

For private keys (like deploy keys), use this method:

config.vm.provision "shell", inline: <<-SHELL
  mkdir -p /home/vagrant/.ssh
  echo "-----BEGIN RSA PRIVATE KEY-----
  YOUR_PRIVATE_KEY_CONTENTS_HERE
  -----END RSA PRIVATE KEY-----" > /home/vagrant/.ssh/id_rsa
  chmod 600 /home/vagrant/.ssh/id_rsa
SHELL

To ensure keys persist after reloads:

config.trigger.after :up do |trigger|
  trigger.run = {inline: "cp /vagrant/keys/id_rsa ~/.ssh/ && chmod 600 ~/.ssh/id_rsa"}
end

If issues persist:

  1. Verify paths with vagrant ssh -c "echo \$HOME"
  2. Check permissions with vagrant ssh -c "ls -la ~/.ssh"
  3. Test SSH connectivity with vagrant ssh -c "ssh -T git@github.com"

When working with Vagrant, many developers encounter a frustrating scenario: provisioning SSH keys only to find them overwritten during subsequent operations. The root cause lies in how Vagrant handles the default ~/.ssh directory during vagrant up or vagrant reload operations.

From your example, we can see the sequence:

# Provisioning copies the key successfully
config.vm.provision :shell, 
:inline => "cp /svr/conf.d/.ssh/id_rsa.mediapop /home/ubuntu/.ssh/id_rsa"

# But post-provisioning, the directory gets reset
vagrant ssh -c "ls -l ~/.ssh"
total 4
-rw-r--r-- 1 vagrant vagrant 409 Mar 20 04:47 authorized_keys

Method 1: Using Provisioning with Proper Permissions

config.vm.provision "shell", inline: <<-SHELL
  mkdir -p /home/vagrant/.ssh
  cp /svr/conf.d/.ssh/id_rsa.mediapop /home/vagrant/.ssh/id_rsa
  chmod 600 /home/vagrant/.ssh/id_rsa
  chown -R vagrant:vagrant /home/vagrant/.ssh
SHELL

Method 2: Leveraging Vagrant Triggers

config.trigger.after :up do |trigger|
  trigger.run = {
    inline: "cp /svr/conf.d/.ssh/id_rsa.mediapop /home/vagrant/.ssh/ && 
            chmod 600 /home/vagrant/.ssh/id_rsa"
  }
end

Method 3: Persistent Synced Folder Approach

config.vm.synced_folder ".ssh", "/home/vagrant/.ssh",
  owner: "vagrant",
  group: "vagrant",
  mount_options: ["dmode=700", "fmode=600"]
  • Always verify file permissions (600 for private keys)
  • Consider using ssh-agent forwarding as an alternative
  • For production environments, use encrypted data bags or vaults

If keys still don't persist, check:

# Verify the Vagrant user's home directory
vagrant ssh -c "echo $HOME"

# Check provisioning timing
config.vm.provision "debug", type: "shell",
  run: "always",
  inline: "date >> /tmp/provision_timestamp.txt"