Setting up libvirt with DNS resolution for Vagrant

Over time there have been multiple solutions on how to get hosts to communicate with each other. Back in 2013 Dominic already wrote Automatic DNS updates from libvirt guests and the approach I’m taking here is a more automated way, taking advantage of developments in the Linux ecosystem since then.

For context, I’m using this on Fedora 44 but I expect it to work on any Linux.

The first part is that your network needs to have a domain set up so libvirt will configure dnsmasq properly. If you already have a network, you can use virsh or virt-manager.

virsh net-edit default

Now make sure a domain entry with the right name exists:

<network>
  <domain name='example.com'/>
</network>

After you restart the network:

virsh net-stop default
virsh net-start default

This is enough for hosts to be able to resolve each other.

When using Vagrant, you can take inspiration from Set the libvirt management domain · theforeman/foremanctl@2eb60da · GitHub to see how Vagrant can also create this network from scratch.

It’s also really great if you don’t need to maintain /etc/hosts on your host so I like to set up systemd-resolved to direct the domain to the right nameserver. I’ve written a hook to do so. As root, run the following

curl --location --output /etc/libvirt/hooks/network https://github.com/voxpupuli/setup-vagrant/raw/refs/heads/v0/network-hook
chmod +x /etc/libvirt/hooks/network
# Needed on Fedora
semanage boolean --modify --on virt_hooks_unconfined

Restart the network as shown before. I also needed to restart libvirtd.service for the SELinux boolean to take effect, but after it should look like this:

$ resolvectl status virbr0
Link 7 (virbr0)
    Current Scopes: none
         Protocols: -DefaultRoute LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported
       DNS Servers: 192.168.122.1
        DNS Domain: example.com
     Default Route: no
1 Like