Skip to main content

Article #1 · 29 July 2026 · 3 min read

Down the Rabbit Hole: Breaking NanoMDM, Decoding .mobileconfig, and Finding Fleet

If you've ever looked at the licensing costs for enterprise Mac management and thought, “How hard could it be to just run an open-source MDM?” — you're not alone. I recently went down that exact rabbit hole.

My goal was simple: find a lightweight, open-source Mobile Device Management (MDM) solution to manage a mixed fleet. What I got was a crash course in Apple's underlying management architecture.

The NanoMDM Stumbling Block

I started my journey with NanoMDM. It's built heavily around microservices and is incredibly lightweight, which appealed to the minimalist in me. I spun up the binaries, got my database connected, and attempted my first device enrollment.

It failed instantly.

The Mac simply refused to install the enrollment profile, throwing a highly generic and unhelpful “Profile installation failed” error. Digging into the macOS Console logs (syslog), I realized the issue wasn't actually NanoMDM itself, but a chain-of-trust failure. My SCEP (Simple Certificate Enrollment Protocol) server was handing out an Identity Certificate that macOS didn't inherently trust, causing the entire MDM payload to be rejected before it even tried to talk to Apple Push Notification service (APNs).

Fixing that certificate chain was frustrating, but it forced me to pop the hood on how Apple actually handles device management.

The Aha! Moment: Decoding .mobileconfig

When you enroll a Mac or push a policy, you're really just delivering a .mobileconfig file. Before this, I thought of these as proprietary black boxes. In reality, they are just XML-based Property Lists (plists).

Opening a .mobileconfig in a text editor reveals the matrix. You have a PayloadContent array filled with specific configurations (like enforcing FileVault or setting Wi-Fi credentials). Every single action requires:

  • PayloadIdentifier: A unique reverse-DNS string (e.g., com.apple.mdm).
  • PayloadUUID: A unique identifier so the OS can track if a profile is being installed, updated, or removed.
  • PayloadType: The specific Apple-defined schema that tells the OS which daemon should handle the settings.

Once a device accepts the com.apple.mdm payload, it establishes a persistent, mutually authenticated TLS connection with your MDM server. From there, the server uses APNs to silently “wake up” the device, prompting it to check in and pull down new XML payloads. It's an incredibly elegant push-and-pull system once you understand the cryptography holding it together.

Pivoting to Fleet (FleetDM)

While researching my SCEP issue, I stumbled onto Fleet (formerly FleetDM). I already knew them for their work with Osquery (which turns operating systems into queryable SQL databases), but I didn't realize they had aggressively built out open-source MDM capabilities.

I decided to pivot. I pulled down their docker-compose stack and fired it up.

The experience was night and day. Because Fleet abstracts a lot of the brutal PKI (Public Key Infrastructure) requirements out of the box, I was able to get an APNs certificate loaded and my first .mobileconfig pushed within an hour.

Even better? It wasn't just a Mac win. I installed the fleetd agent on a Windows machine, and it registered instantly in the same dashboard. Managing macOS profiles via Apple's native MDM protocol, while simultaneously pulling deep telemetry from Windows via Osquery — all in one open-source Docker container — felt like a massive win.

Troubleshooting NanoMDM was a headache, but it gave me the exact foundational knowledge I needed to appreciate what Fleet is doing right.

So, that's my weekend rabbit hole. What MDM are you currently running in your stack?