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


2 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"