Fork me on GitHub

wamonomicon

Tag: Vagrant

IP lookup for Vagrant private networking

I haven't posted in ages and given I'm doing so much interesting stuff with SpatialBuzz these days, I felt I needed to post something, however short but sweet.

I spin up a lot of dev instances with Vagrant and VirtualBox on OS X these days and needed them to be host addressable on fixed IPs. I also wanted a single source for managing said IPs. After trying several Vagrant plugins, playing with DHCP and tweaking pf rules, the easiest solution I found was a local DNS server and getting the Vagrantfile to look up its own IP.

30-second guide to local DNS on OS X1

  • Install dnsmasq via Homebrew
  • Add your desired homename and IPs to the end of the default config file /usr/local/etc/dnsmasq.conf in the format address=/<host name>/<IP address> e.g.:-

    address=/db.vagrant.dev/192.168.2.10
    address=/web.vagrant.dev/192.168.2.11
  • Start your local DNS server with the following command (and stop it with unload):-

    sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
  • Tell OS X to use it for a domain by creating the file /etc/resolver/<domain> e.g. /etc/resolver/vagrant.dev with the contents:-

    nameserver 127.0.0.1
  • Check the resolver is listed with:-

    scutil --dns
  • Query it directly with:-

    dig db.vagrant.dev @127.0.0.1

Vagrantfile

Here's a basic Vagrantfile to configure a single instance with the host-only network address read from DNS. As the host name is specified as a parameter, this works for multi-machine setups too. The VM is both addressable via vagrant ssh and SSH directly to the host name.

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

# Set default to virtualbox unless otherwise specified
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'virtualbox'

# hostname.wamonite.com: private IP address read from local DNS
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    config.vm.box = "hashicorp/precise64"

    # Set the hostname
    config.vm.hostname = "web.vagrant.dev"

    # Read the IP address from local DNS and set as private network IP
    ip = Socket::getaddrinfo(config.vm.hostname, 'http', nil, Socket::SOCK_STREAM)[0][3]
    config.vm.network "private_network", ip: ip
end

Guest VM lookups

On VirtualBox the DNS server is available on the .1 address of the specified class C network, so VMs can address each other if the name resolution for the guest OS is configured appropriately. In the above example, for a Linux host /etc/resolv.conf would need to contain:-

nameserver 192.168.2.1
domain vagrant.dev

  1. Another guide with detailed commands can be found at 'Never touch your local /etc/hosts file in OS X again' 

Posted Sat 12 Jul '14 in Dev (Vagrant, OS X, VirtualBox)