30
votes

I am managing multiple VMs with Vagrant. Networks are configured as private, ip addresses have been set and hostnames are assigned. As shown in the Vagrantfile below.

The VMs can communicate with each other via the IP address, but I would like to know how to allow VMs to communicate using their assigned hostname. I.e. How to make ping comtest2 work from comtest1?

Vagrantfile:

Vagrant.configure("2") do |config|

  config.vm.define "comtest1" do |comtest1|
    comtest1.vm.box = "precise32"
    comtest1.vm.hostname = "comtest1"
    comtest1.vm.network "private_network", ip: "192.168.10.21"
  end

  config.vm.define "comtest2" do |comtest2|
    comtest2.vm.box = "precise32"
    comtest2.vm.hostname = "comtest2"
    comtest2.vm.network "private_network", ip: "192.168.10.22"
  end

end
5

5 Answers

16
votes

You can use Zeroconf. It broadcasts the host name in network and makes it available to the other hosts on the local network. That way you can access your hosts using test1.local, test2.local, etc.

Just install avahi-daemon and libnss-mdns!

Example

Vagrantfile:

Vagrant.configure("2") do |config|
  
  config.vm.box = "ubuntu/bionic64"
  
  config.vm.define "vm1" do |machine|
    machine.vm.hostname = "vm1"
    machine.vm.network "private_network", type: "dhcp"
  end

  config.vm.define "vm2" do |machine|
    machine.vm.hostname = "vm2"
    machine.vm.network "private_network", type: "dhcp"
  end
  
  # allow guests to reach each other by hostname
  config.vm.provision "allow_guest_host_resolution",
    type: "shell",
    inline: <<-SHELL
      apt update
      apt install -y avahi-daemon libnss-mdns
    SHELL
    
end

Test

$ vagrant up
...
$ vagrant ssh vm1 -- ping -c 1 vm2.local
PING vm2.local (172.28.128.8) 56(84) bytes of data.
64 bytes from 172.28.128.8 (172.28.128.8): icmp_seq=1 ttl=64 time=0.333 ms

$ vagrant ssh vm2 -- ping -c 1 vm1.local
PING vm1.local (172.28.128.7) 56(84) bytes of data.
64 bytes from 172.28.128.7 (172.28.128.7): icmp_seq=1 ttl=64 time=0.254 ms
5
votes

It isn't the most elegant solution in the world but it is very simple, how about something like:

Vagrant.configure("2") do |config|

  config.vm.define "comtest1" do |comtest1|
    comtest1.vm.box = "precise32"
    comtest1.vm.hostname = "comtest1"
    comtest1.vm.network "private_network", ip: "192.168.10.21"
    comtest1.vm.provision "shell", inline: <<-SHELL
       sed -i '$ a 192.168.10.22 comtest2' /etc/hosts           
    SHELL
  end

  config.vm.define "comtest2" do |comtest2|
    comtest2.vm.box = "precise32"
    comtest2.vm.hostname = "comtest2"
    comtest2.vm.network "private_network", ip: "192.168.10.22"
  end

end
1
votes

If the host resolves DNS correctly, then you can configure Virtualbox to use the host as the DNS resolver.

config.vm.provider :virtualbox do |vb|
  vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
end

See https://serverfault.com/a/506206/250071


We use a local Ansible task to automatically add the provisioned box to the host /etc/hosts file. It is a little awkward, but has been very robust.

- setup:
  gather_subset: [network]
- name: Add host mapping to local /etc/hosts
  delegate_to: 127.0.0.1
  lineinfile: dest=/etc/hosts regexp=".+{{ vm.hostname }}$" line="{{ ansible_all_ipv4_addresses|sort|last }} {{ vm.hostname }}"
0
votes

Check out landrush on Github. It will setup a DNS for your vagrant private network.