Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@shadyvb
Last active March 31, 2024 17:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save shadyvb/cd06ee086ab0f1f8e0898717a2f036f3 to your computer and use it in GitHub Desktop.
Save shadyvb/cd06ee086ab0f1f8e0898717a2f036f3 to your computer and use it in GitHub Desktop.
VagrantFile hack to auto-create ssh-config entries for vagrant machines

TL;DR;

This will let you SSH into any vagrant machine quickly, using its host name, and without further manual steps.

Quick setup:

# Create the ~/.ssh/config.d folder
mkdir ~/.ssh/config.d &>/dev/null

# Make sure it is included in your ~/.ssh/config
bash -c "if ! grep -q 'Include ~/.ssh/config.d/*' ~/.ssh/config; then cp ~/.ssh/config ~/.ssh/config.backup; { echo 'Include ~/.ssh/config.d/*'; cat ~/.ssh/config; } | tee ~/.ssh/config >/dev/null; fi"

# Copy the global VagrantFile to your ~/.vagrant.d
curl https://gist.githubusercontent.com/shadyvb/cd06ee086ab0f1f8e0898717a2f036f3/raw/834fb36fe1fd99afeacf189886e89ee3d0e62640/VagrantFile > ~/.vagrant.d/VagrantFile

Explanation:

  • Apparently.. you can have a global VagrantFile! And that gets executed for all vagrant machines, and can be found/created at ~/.vagrant.d/VagrantFile.
  • As a workaround to slow vagrant ssh calls, this piece of code will auto-create a new ssh_config entry under ~/.ssh/config.d each time you do a vagrant up, so you can just ssh HOSTNAME.LOCAL any time and get a milliseconds execution time, instead of the many seconds you get with vagrant ssh
  • In order for your SSH config to pick up the new config files, you need to include the new folder in your ~/.ssh/config file by adding the following to the beginning of the file: Include ~/.ssh/config.d

Try it!

  • Do a vagrant up on any of your vagrant machines
  • Assuming your vagrant machine host name is: client.local
  • Try to ssh cient.local

Next up:

  • I've been expirementing with a magical dynamic ssh vagrant command that detects SSH connection information from the vagrant machine in the current folder, for which I've been playing with the ProxyCommand directive which can be scripted. But performance isn't the same as using the direct ssh HOSTNAME.LOCAL trick enclosed. Still an interesting idea nonetheless.
Vagrant.configure("2") do |config|
config.trigger.after :up,
name: "Caching vagrant ssh-config for '#{CONF['hosts'].join('\' and \'')}'",
ruby: proc{|env,machine| puts `mkdir ~/.ssh/config.d &>/dev/null; vagrant ssh-config | sed 's/Host default/Host #{CONF['hosts'].join(" ")}/' | tee ~/.ssh/config.d/vagrant-#{CONF['hosts'][0]} >/dev/null; bash -c "if ! grep -q 'Include ~/.ssh/config.d/*' ~/.ssh/config; then echo '> Please add the following line to your ~/.ssh/config file: Include ~/.ssh/config.d/*'; fi"`}
end
@avoidik
Copy link

avoidik commented Mar 31, 2024

if you're looking for a ruby idiomatic option to accomplish the same, here it is:

require Vagrant.source_root.join("plugins/commands/ssh_config/command")

Vagrant.configure(2) do |config|
  config.vm.define "ubuntu" do |ubuntu|
    ubuntu.vm.box = "ubuntu"
    ubuntu.trigger.after :up do |trigger|
      trigger.ruby do |env,machine|
        ssh_template = VagrantPlugins::CommandSSHConfig::Command.new(["--host", machine.name.to_s, machine.name.to_s], env)
        ssh_config = File.join(File.expand_path('~'), '.ssh', 'config.d', machine.name.to_s)
        $stdout = File.new(ssh_config, 'w')
        ssh_template.execute
        $stdout = STDOUT
      end
    end
    ubuntu.trigger.after :destroy do |trigger|
      trigger.ruby do |env,machine|
        ssh_config = File.join(File.expand_path('~'), '.ssh', 'config.d', machine.name.to_s)
        File.delete(ssh_config) if File.exist?(ssh_config)
      end
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment