31

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
Charles
  • 50,943
  • 13
  • 104
  • 142
Nick
  • 6,366
  • 5
  • 43
  • 62

5 Answers5

19

Cheat the dns resolution with https://github.com/adrienthebo/vagrant-hosts ?

mestachs
  • 1,889
  • 15
  • 17
  • 4
    Shouldn't there be a more legit way instead of using a plugin and "cheating"? I wonder whether this limitation comes from the VM provider or Vagrant. – vervas Jan 09 '15 at 10:43
  • The [@neutrinus](https://stackoverflow.com/a/30780347/4396730) answer is the simplest approach – Filip Seman May 03 '22 at 14:30
16

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
Filip Seman
  • 1,252
  • 2
  • 15
  • 22
neutrinus
  • 1,879
  • 2
  • 16
  • 21
  • 2
    This seems to work and looks like the easiest way to communicate. – Jalpesh Jul 10 '15 at 21:14
  • What's the rest of the `Vagrantfile` look like if this is used? (Not the provisioning of those packages, but the networking, machine naming, etc.) – Jamie Jackson Oct 09 '19 at 18:36
  • Never mind. I figured it out and added a functioning example. – Jamie Jackson Oct 09 '19 at 21:14
  • While in principal this seems like a great idea your actual results may vary. mDNS doesn't work for apps that perform true NS resolution, which is often the case for things written in Go. I ran into this specifically while trying to setup Prometheus, but found instances of the same issue with Docker. (see: https://github.com/docker/machine/issues/3297) – MrJohnBBQ Mar 09 '22 at 06:12
5

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
Mark McLaren
  • 11,470
  • 2
  • 48
  • 79
1

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 }}"
Ryan
  • 4,594
  • 1
  • 32
  • 35
0

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

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Gordon Sun
  • 278
  • 1
  • 19
  • 1
    Whilst this may theoretically answer the question, [it would be preferable](//meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Tunaki Jan 29 '16 at 09:36
  • This appears to be working only for Linux hosts. Seems to have a pre-req for `iptables`. – Dennis Apr 24 '17 at 16:06