I recently delved into the world of macos service management, and thought I’d share a few tidbits that may help someone else out there.

I decided to try to get dnsmasq running on my mac. Why? Well, I didn’t really need it, there was no functionality I needed I couldn’t get with resolvers and etc/hosts, but I thought it would be good to learn more about the computer I spend my most time on, and how it handles tasks I’ve mostly only handled using linux.

So I installed dnsmasq like I’ve installed many other things on my mac, using brew install dnsmasq. After a bit of googling about the best way to run dnsmasq on a mac I came across the homebrew page.

Maybe you, like me, had never heard of homebrew services before? Maybe you thought homebrew was just for package management? Well, for some reason, it turns out the authors of homebrew also wanted their package manager to be a service manager. Enter the idea of brew services.

After a bit of research, I learned that brew service are really just light wrappers around the native macos service manager, launchctl.

When you run brew service start dnsmasq what really happens is brew makes a symlink from the brew dnsmasq package .plist file to /Library/LaunchAgent or /Library/LaunchDaemon depending on whether you run as root as your own user.

Wrapping a service manager around another service manager feels a bit messy, especially when the packaged version of dnsmasq from homebrew already contains the native plist file to run brew as a launchd service.

So here’s what I did to get dnsmasq working without using brew services:

~ $ sudo cp /usr/local/Cellar/dnsmasq/2.79/homebrew.mxcl.dnsmasq.plist /Library/LaunchDaemons/
~ $ sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
~ $ sudo launchctl start homebrew.mxcl.dnsmasq

If you’d like the service to start on boot, just add a <true/> tag after the <key> tag containing the value RunAtLoad, like so:

    <key>Disabled</key>          <false/>
    <key>RunAtLoad</key>         <true/>
    <key>KeepAlive</key>         <false/>
    <key>LaunchOnlyOnce</key>    <true/>

Note I placed the plist file in the LaunchDaemons directory because I want this process to start as root because I need to bind the privileged port 53.