How to Make dnsmasq Automatically Reload /etc/hosts Changes Without Manual Restart


2 views

Many developers encounter this frustration: after adding entries to /etc/hosts or custom files like /etc/hosts.dnsmasq, dnsmasq stubbornly refuses to recognize the changes without a manual service restart. This becomes particularly annoying during development when constantly testing domain configurations.

By design, dnsmasq reads host files only at startup. This conservative approach ensures stability but creates workflow friction. The daemon doesn't monitor file changes because:

  • Original design focused on lightweight DNS caching
  • Frequent file checks could impact performance
  • Some deployments prefer explicit control over DNS changes

Method 1: inotify Trigger Script

This approach uses Linux's filesystem monitoring:


#!/bin/bash
while inotifywait -e modify /etc/hosts /etc/hosts.dnsmasq; do
    systemctl reload dnsmasq
    logger "dnsmasq reloaded due to hosts file change"
done

Save as /usr/local/bin/watch_hosts.sh, make executable, and run as service.

Method 2: systemd Path Unit

Create /etc/systemd/system/dnsmasq-reload.path:


[Unit]
Description=Monitor hosts files for dnsmasq

[Path]
PathModified=/etc/hosts
PathModified=/etc/hosts.dnsmasq

[Install]
WantedBy=multi-user.target

Then create matching service file /etc/systemd/system/dnsmasq-reload.service:


[Unit]
Description=Reload dnsmasq after hosts change

[Service]
Type=oneshot
ExecStart=/bin/systemctl reload dnsmasq

Method 3: dnsmasq Exec Hook

Add to /etc/dnsmasq.conf:


conf-file=/etc/hosts.dnsmasq
dhcp-hostsfile=/etc/hosts.dnsmasq
no-hosts  # Disable default /etc/hosts reading

Then use this post-processing script:


#!/bin/bash
while true; do
    inotifywait -e modify /etc/hosts.dnsmasq
    kill -SIGHUP $(cat /var/run/dnsmasq/dnsmasq.pid)
done

After implementing any solution:

  1. Test with dig @localhost example.com
  2. Check logs: journalctl -u dnsmasq --since "5 minutes ago"
  3. Verify PID file location matches your system

For containerized environments:

  • Bind-mount hosts file into container
  • Use --dns-opt='options:debug' in Docker
  • Consider dnsmasq alternatives like CoreDNS when auto-reload is critical

Many sysadmins and developers encounter this issue - after modifying /etc/hosts or a custom hosts file like /etc/hosts.dnsmasq, dnsmasq stubbornly refuses to recognize the changes without manual intervention. This behavior persists even when dnsmasq is configured to read these files.

By design, dnsmasq doesn't actively monitor files for changes. It loads host entries only:

  • At startup
  • When explicitly told to reload (via SIGHUP)
  • When the maximum cache size is reached (triggering a flush)

Here are three effective approaches to solve this:

1. Inotify-triggered Reload

Using inotifywait to monitor changes:

#!/bin/bash
while inotifywait -e modify /etc/hosts /etc/hosts.dnsmasq; do
    pkill -HUP -x dnsmasq
done

2. Systemd Path Unit

Create /etc/systemd/system/dnsmasq-reload.path:

[Unit]
Description=Monitor hosts files for changes

[Path]
PathModified=/etc/hosts
PathModified=/etc/hosts.dnsmasq

[Install]
WantedBy=multi-user.target

Then create /etc/systemd/system/dnsmasq-reload.service:

[Unit]
Description=Reload dnsmasq

[Service]
Type=oneshot
ExecStart=/bin/kill -HUP $(cat /run/dnsmasq/dnsmasq.pid)

3. Custom Cron Script

For simpler implementations:

*/5 * * * * root [ /etc/hosts -nt /var/lib/dnsmasq/hosts.timestamp ] && pkill -HUP dnsmasq && touch /var/lib/dnsmasq/hosts.timestamp

Ensure your dnsmasq.conf contains:

no-hosts                  # Ignore /etc/hosts by default
addn-hosts=/etc/hosts     # Explicitly include
addn-hosts=/etc/hosts.dnsmasq  # Additional hosts file

After implementation, test with:

# Add test entry
echo "127.0.0.1 test.local" >> /etc/hosts

# Check if resolved
dig test.local @127.0.0.1 | grep -A1 "ANSWER SECTION"