zeroconf aka bonjour

Zeroconf is great because it allows local servers and services to advertise
their capabilities over the local network, without needing a central DNS server.
With virtual machines and vagrant workflows, you will find resources such as ssh
access are on different IPs depending on what network you are working from, or
which hosts were started first.

Being able to look hosts and services up using DNS makes this really easy. Most
UNIX-like OS include a dns-sd service discovery tool that does this for you,
enumerating advertised domains, services, and servers, and obviously you can
include this functionality in any applications you write as both DNS and mDNS
are readily available. For example I can ssh to wintermute.local without
needing to know what DHCP address has been assigned to that instance.

Instead of remembering and maintaining IP addresses for machines and services,
you can simply have the server publish them over the zeroconf protocol when it
starts up, using DHCP and the mDNS protocol, and make them immediately
available to any machine that has zeroconf-enhanced DNS lookups.

To support local domain lookups, you’ll need to enable mDNS and change the
nameserver lookup method to try mDNS before falling back to DNS. This works
OOTB on Apple systems, and is trivial to enable for most other UNIX platforms.

/etc/nsswitch.conf

Replace the ^hosts: line like so:

hosts: files mdns_minimal [NOTFOUND=return] dns mdns

That’s the lookup end taken care of, now we need to get the records generated
and broadcast when the vagrant box starts up. Sadly, With FreeBSD 10.1, a
number of annoying little things changed. The mdnsresponderposix package
changed its name and the flags and rc.conf settings have also changed
since 10.0. The config file format is completely barmy, but it is what it
is.

/usr/local/etc/mdnsresponder.conf

The simple and clear config file format below is no longer acceptable;

loader.conf

RAMdisk for speed

The actual RAM used is dependent on the data in the RAMdisk, you should make
a sensible limit so your ramdisk can’t bring down the machine itself. The
size parameter is in bytes, so the above size is 3GiB. I leave a minimum
of 1 GiB to ensure my OS doesn’t completely tank if I accidentally fill up
the entire ramdisk.

sudo

I put sudo configs in their own file /usr/local/etc/sudoers.d/ansible for
example.

ssh

This needs to be appended to /etc/ssh/sshd_config and then without closing
your existing ssh session, so service sshd restart. sshd is cowardly and
won’t restart if the config isn’t valid, but you can still easily lock
yourself out if you’re not very careful.

Port 2200
UseDNS no
PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no

Boxing for Vagrant

Finally, we want to package the new VM as a vagrant box. Just before
shutting down the box, we will do some cleanup:

remove unnecessary packages and their cache directory

remove all the host private ssh keys, they’ll be recreated on next boot

Then shut down the VM and VMware Fusion completely, and prepare the VM
for vagrant. This process is very simple, but I’m amazed it isn’t documented
anywhere. In brief, a vagrant box is simply a tarball of the files that
comprise a VM, and a little metadata.json file containing the type of VM
this was created from. The hardest part is working out where your VM is
located.

From the directory of your Vagrantfile, there’s a hidden folder tree,
similar to this one:

However it’s possible that this directory was customised somewhat. You
should always be able to find it via find . -type f -name '*.vmx'. Change
to that directory and run these. For the .vmdk there can be several
different files, but only the first one (shortest name) is usually required
to be shrunk; the rest will spit out spurious warnings if processed.