Munki and plist Files: How One Folder of Text Serves Software for Mac Clients

Hero image for Munki and plist Files: How One Folder of Text Serves Software for Mac Clients
PC Drama
88 views

macOS Software Management, Without the Drama

Munki is a powerful open-source tool for managing software across macOS systems.

Instead of waiting for users to click "Update," automations handle the installs for you. Once a Mac is pointed at your managed software catalog, pre-configured client Macs can pull apps, updates, or even uninstall applications with zero drama on the client side.

By the end of this page, you'll understand exactly how Munki clients are managed using nothing but plain .plist files sitting on an ordinary web server, why that deliberately boring design is secretly brilliant, and the one critical permission question that determines whether it's also truly safe.

Watch: how Munki provisions software across a Mac fleet from a folder of plist files.

Here is the answer first, no warm-up. Munki is an open-source macOS software management system whose entire control plane is a directory of Apple property-list (plist) text files, served as static files by a plain web server. No application server. No database. No magic. Just files.

TL;DR

  • What it is: Munki is a collection of open-source tools, licensed Apache 2.0, that manage software installation and configuration across macOS machines.
  • Where it came from: lead-developed by Greg Neagle and released as open source by Walt Disney Animation Studios.
  • How it works: the repo's brain is three kinds of plist files. pkginfo describes each installer item, catalogs roll those up, and manifests say what each machine should have.
  • What serves it: "A basic Munki server is simply a web server." Static files, no app server, no database. You can even host it in the cloud.
  • The catch: if your control plane is editable text files, then whoever can write to those files, or to the web server, owns your updates and installations Security becomes a file-permission question.

Why use Munki?

Munki is a macOS software management toolset solution for a small business's with a need to manage and control installations, updates, and remove software on managed Macs using a simple web-server-based repository of packages. Munki is licensed under the permissive Apache License 2.0, so you can read every line, fork it, and run it without asking anyone's permission. You can browse the project on GitHub or at its home, munki.org.

For example, a small business with 20–50 Macs can use Munki to keep security tools, browsers, and productivity apps updated across all machines. Instead of manually updating each one or paying for an expensive MDM solution, they set up Munki once. Required apps install automatically, optional tools appear in a self-service catalog for users, and everything stays current with minimal ongoing effort.

The origin story is the first surprise. Munki was lead-developed by Greg Neagle, a Staff Systems Engineer at Walt Disney Animation Studios, and released as open source by the studio itself. The same place that renders animated hair frame by frame quietly built one of the most widely used Mac management frameworks on the planet and then gave it away. Not bad for a side effect of keeping the animators' workstations stocked.

Definition: Munki

Munki is an open-source software deployment framework for macOS. A client tool on each Mac periodically reads a repository of plain files over HTTP or HTTPS, works out what should be installed or removed, and makes it so. It is configuration and software management, not device enrollment.

See It in the GUI: MunkiAdmin and Managed Software Center

Everything above is true at the command line, but you do not have to live there. The exact same repo and client model has two friendly faces: MunkiAdmin for the repo, and Managed Software Center for the Mac on the receiving end. Here is the whole chain, clicked through instead of typed.

MunkiAdmin is the visual face of the repo (it stands in for ls, plutil, makecatalogs, and manifestutil), and Managed Software Center is the visual face of the client (the user-facing side of managedsoftwareupdate). Same plist model, friendlier surface.

Part A — The repo, in MunkiAdmin

MunkiAdmin is a free, native macOS app for browsing and editing a Munki repo. It is a third-party tool (by Hannes Juutilainen), not part of Munki itself, but it is the de facto standard GUI. It reads your existing repo as-is, no reconfiguration needed.Source: MunkiAdmin on GitHub — "designed to complement your current workflow… doesn't require any configuration or changes to your repository."

Install it (current version 1.10.1)

brew install --cask munkiadmin
# or grab the .app from the Releases page:
# https://github.com/hjuutilainen/munkiadmin/releases

Requires macOS 10.13+ and the Munki tools installed.Source: Homebrew — munkiadmin cask.

Before you point it at a production repo: MunkiAdmin writes directly to your repo files, and its own README calls it "still incomplete," so take a backup first (or if your repo is in Git, commit a clean state). On a small inherited setup this is cheap insurance.Source: MunkiAdmin README.

The sidebar is the repo directories

Open your repo (File → Open, point at the repo root) and the left sidebar maps almost 1:1 onto the plist file types we walked through above:

Below is a simulated MunkiAdmin loaded with sample data. Click the sidebar sections, then click any row to drill in. Your real repo shows your own packages and Macs, but the layout and behavior match.

MunkiAdmin — sample_repo
Repository
📦Packages 13
📚Catalogs 2
📄Manifests 5
Organize
🏷️Categories
👤Developers
🗂️Directories
📦 PackagesYour pkgsinfo/ (the metadata) joined to pkgs/ (the bytes). Each row is one installer item: name, version, and the catalogs it belongs to. Click one to edit its pkginfo in a form instead of raw XML.
📚 CatalogsYour catalogs/. Click testing or production to see exactly which package versions live there. Try it in the simulator above: clicking a catalog filters the Packages list to that shelf.
📄 ManifestsYour manifests/. Click one to see its catalog list (ordered!) and its managed_installs / optional_installs / managed_uninstalls as editable lists.
🏷️ Categories / 👤 DevelopersConvenience groupings MunkiAdmin derives from pkginfo fields — handy filters, not extra repo directories.
The same rule still rules — MunkiAdmin just hides the command. When you change a package's catalog membership or edit a pkginfo and hit save, MunkiAdmin runs makecatalogs for you. You still never hand-edit the catalogs directly; the GUI simply turns "edit pkginfo, rebuild catalogs" into one click.Concept: Munki Wiki — Makecatalogs.

Walking the resolution chain by clicking

The same resolution chain from above, now as a click-path:

1 · Manifests →Click the manifest matching a Mac's ClientIdentifier. Read its catalogs (note the order) and its managed_installs. This is the shopping list.
2 · Catalogs →Click a catalog that manifest searches. See which versions are on the shelf. First match in the manifest's catalog order wins.
3 · Packages →Click the matched item. See its version, its installs / receipts rules, and the file it points to in pkgs/. This is the product spec plus the box.

Part B — The client, in Managed Software Center

On a managed Mac, Managed Software Center (in /Applications) is the user-facing end of the chain, what a person sees after the client resolves its manifest. It runs as the logged-in user.Source: Munki Wiki — Managed Software Center.

Updates tabPending managed_installs / managed_updates — the mandatory stuff the manifest says this Mac must have.
Software / CategoriesThe optional_installs from the manifest — a self-service "store" the user can install from without admin rights, and remove later.

So the same manifest you clicked in MunkiAdmin (Part A) is what populates these tabs (Part B). One list, authored on the repo, rendered on the Mac. That is the whole chain, end to end, without touching a terminal.

Do it on your real setup

Hands-on · Repo (MunkiAdmin)
  1. Install MunkiAdmin (brew install --cask munkiadmin) and back up or commit your repo first.
  2. File → Open → point at your repo root. Confirm the sidebar shows Packages, Catalogs, and Manifests with counts that feel right for your fleet.
  3. Click Manifests, open the one matching a Mac you know. Read its catalog order and its managed and optional installs; this should match the raw manifest plist from earlier.
  4. Click a package in Packages. Find the catalogs checkboxes (which catalogs it belongs to) and its version. Don't change anything yet, just locate them.
Hands-on · Client (Managed Software Center)
  1. On a managed Mac, open Managed Software Center from /Applications.
  2. Check the Updates tab (what's mandated) and the software / optional view (the self-service store).
  3. Cross-check: do the optional items shown here match the optional_installs you saw in that Mac's manifest in MunkiAdmin? That is the chain proven from both ends.

Quick check — UI to model

Map what you see in the GUI back to the mental model. Click an answer for instant feedback.

1. In MunkiAdmin, which sidebar section do you not edit directly, because saving a package change regenerates it?

Right. Catalogs are still build artifacts — MunkiAdmin just runs makecatalogs for you on save. Same rule, one click.
Not that one — you actively edit Manifests and Packages. Catalogs stay a generated artifact; MunkiAdmin rebuilds them when you save a package change.

2. You want a specific Mac to start getting Slack. Which MunkiAdmin section do you edit?

Correct. The manifest is the per-Mac shopping list. The Slack package can already exist in a catalog; you just add it to that machine's manifest.
Close, but those are about availability, not assignment. The package may already be in the catalog — to make this Mac get it, add Slack to that manifest's managed_installs.

3. A user should be able to install an app themselves, without admin rights. Where does it belong, and where do they get it?

Exactly. optional_installs in the manifest become the self-service items in Managed Software Center — install or remove, no admin rights needed.
Not quite. Self-service means optional_installs in the manifest, which surface in Managed Software Center's store view. managed_installs are mandatory, not user-chosen.

4. MunkiAdmin shows a package at version 120 in the testing catalog, but a production Mac isn't offered it. The Mac's manifest searches only production. Best fix in the UI?

Right. Catalog membership lives in the package's pkginfo; tick production and save, and MunkiAdmin regenerates the catalogs. Never hand-edit catalog files.
No — never hand-edit catalogs, and deleting testing fixes nothing. Membership is a pkginfo property: in Packages, check production for the item and save; MunkiAdmin rebuilds the catalogs.

What Is a plist File?

Stacked translucent glass layers forming a nested key-and-value tree, representing the structure of a property list file
A plist is just structured key-and-value data, stacked neat enough for a human to read over a shoulder.

A plist, short for property list, is Apple's native format for structured data. It comes in a human-readable XML flavor, a compact binary flavor, and an older legacy ASCII form. macOS and iOS lean on plists everywhere, from app preferences stored through NSUserDefaults to the Info.plist baked into every app bundle. If you have ever poked around a Mac's guts, you have met one.

Apple's own documentation describes the format in plain terms.

"Property lists organize data into named values and lists of values using several object types. These types give you the means to produce data that is meaningfully structured, transportable, storable, and accessible, but still as efficient as possible."

Apple Developer Documentation, Property List Programming Guide

The key word for our purposes is storable. A plist is a file you can open in a text editor, read with your own eyes, diff against yesterday's version, and check into Git. Hold that thought, because it is the whole reason Munki works the way it does.

How Munki Actually Works: pkginfo, Catalogs, and Manifests

Isometric pipeline of three stages, package blocks flowing into a catalog ledger block and then branching into per-machine manifest blocks
Three file types, one clean pipeline: describe the software, list it, then assign it per machine.

Munki's repository runs on three kinds of plist files, and once you know what each one does, the whole system clicks into place. They build on each other like a recipe: ingredients, pantry, then the order ticket for each table.

The Munki documentation is blunt about the format, which saves us a lot of guessing.

"Manifests and catalogs are stored on the web server as standard Apple plist files in text format. pkginfo files are also plist-formatted files."

Munki documentation, project wiki

Here is what each file does:

  • pkginfo is one plist per installer item. It holds the metadata Munki needs to handle a piece of software: its name, version, what it requires, how to detect whether it is already installed, and what to do on update or removal. Think of it as the label on the can.
  • Catalogs are plists built from all those pkginfo files by a tool called makecatalogs. A catalog is the searchable index of everything available in the repo. Think of it as the pantry inventory, assembled from every label.
  • Manifests are plists that say what a given machine, or group of machines, should have installed and what should be removed. Think of it as the order ticket pinned above the stove for each table.
The three Munki plist files

ManagedInstalls.plist

Client preferences · /Library/Preferences/ManagedInstalls.plist

The primary configuration file on the client Mac.

SoftwareRepoURL
https://your-munki-server/repo
ClientIdentifier
your-manifest-name
InstallAppleSoftwareUpdates
true
ShowOptionalInstalls
true
AggressiveUpdateNotificationDays
14
ManagedInstallsDir
/Library/Managed Installs
PackageVerificationMode
hash
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>SoftwareRepoURL</key>
    <string>https://your-munki-server/repo</string>
    <key>ClientIdentifier</key>
    <string>your-manifest-name</string>
    <key>InstallAppleSoftwareUpdates</key>
    <true/>
    <key>ShowOptionalInstalls</key>
    <true/>
    <key>AggressiveUpdateNotificationDays</key>
    <integer>14</integer>
    <!-- Other common keys -->
    <key>ManagedInstallsDir</key>
    <string>/Library/Managed Installs</string>
    <key>PackageVerificationMode</key>
    <string>hash</string>
</dict>
</plist>

Firefox pkginfo

pkginfo · repo pkgsinfo/ · created by munkiimport

One plist describing a single installer item.

catalogs
  • production
display_name
Firefox
installer_type
pkg
item_name
Firefox
name
Firefox
minimum_os_version
10.15
version
latest (or a specific version)
uninstallable
true
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>catalogs</key>
    <array>
        <string>production</string>
    </array>
    <key>display_name</key>
    <string>Firefox</string>
    <key>installer_type</key>
    <string>pkg</string>
    <key>item_name</key>
    <string>Firefox</string>
    <key>name</key>
    <string>Firefox</string>
    <key>minimum_os_version</key>
    <string>10.15</string>
    <key>version</key>
    <string>latest</string>  <!-- or specific version -->
    <key>uninstallable</key>
    <true/>
</dict>
</plist>

manifest

Manifest · repo manifests/

Defines what gets installed on which machines.

catalogs
  • production
managed_installs
  • Firefox
  • GoogleChrome
  • Office365
managed_uninstalls
  • SomeOldApp
optional_installs
  • Slack
  • Zoom
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>catalogs</key>
    <array>
        <string>production</string>
    </array>
    <key>managed_installs</key>
    <array>
        <string>Firefox</string>
        <string>GoogleChrome</string>
        <string>Office365</string>
    </array>
    <key>managed_uninstalls</key>
    <array>
        <string>SomeOldApp</string>
    </array>
    <key>optional_installs</key>
    <array>
        <string>Slack</string>
        <string>Zoom</string>
    </array>
</dict>
</plist>

The client on each Mac does the rest. It downloads the catalogs, reads the detail on individual manifest items, then builds a list of things to install and a list of things to remove. No server-side brain decides anything. The server just hands over files. The decision-making lives entirely in the client reading plain text.

Expert Tip: Treat the repo like source code

Because every manifest, catalog, and pkginfo is a text file, the smartest Munki shops keep the entire repo in version control. Every change to what installs becomes a commit with an author, a timestamp, and a diff. Roll out a bad package and you can git revert your way back to calm. Your change history and your installation history become the same history.

Just a Web Server: Why the Repo Is Boring on Purpose

A single plain web server unit on a shelf in a dim server closet, lit with a faint violet rim light
The Munki server's secret sauce: there is no secret sauce. It serves files and goes back to sleep.

Now for the simplicity of the webserver that hosts the software repo for Munki. The Munki server, serves files. It does not run Munki. It does not need a database. It does not need PHP, Python, or a single line of server-side code. It hands out files and that is the entire job description.

The project documentation puts it about as plainly as it can be put.

"A basic Munki server is simply a web server. You do not need the Munki tools installed on the server. You are simply setting up a filesystem on a web server for clients to access."

Munki documentation, project wiki

This is the surprise that reframes everything. Most management platforms are sprawling applications with their own runtime, their own database, their own attack surface, and their own 2 a.m. outages. Munki's server is a directory tree of static files behind Apache, Nginx, or a cloud bucket. You can host the whole repo in the cloud and never touch a server process. The "platform" is a filing cabinet, and the intelligence rides on the client. Boring is a feature here, not a bug. Fewer moving parts means fewer things that can break, fewer services to patch, and a system you can actually reason about end to end.

Munki Is Not an MDM (and Why That Matters)

Here is the most common mix-up, so let us fence it off cleanly. Munki is not an MDM. It is configuration and software deployment management, categorized alongside configuration management, not Mobile Device Management. An MDM enrolls devices, pushes policy and profiles, and can wipe or lock a Mac through Apple's management protocol. Munki does none of that. It is laser-focused on one job: getting the right software onto the right machines and keeping it there.

In the real world, the two are partners, not rivals. Munki is commonly integrated into deployment workflows alongside an MDM. The MDM handles enrollment, identity, and policy. Munki handles the rich software catalog that MDMs are clumsy at. You let each tool do the thing it is genuinely good at.

Dimension Munki MDM (Jamf, Intune, etc.)
Primary job Software install, update, removal Device enrollment, policy, profiles
Control plane plist files on a web server Vendor service plus Apple's MDM protocol
Can wipe or lock a Mac No Yes
Server requirement Any plain web server Hosted or on-prem management service
Typical role The software catalog Enrollment and the policy backbone

Pro Tip: Run them together, not instead

If you are choosing between Munki and an MDM, you have framed the question wrong. Most mature Mac shops run both: the MDM enrolls and governs the device, and Munki delivers the deep, version-controlled software catalog on top. Asking "Munki or MDM?" is like asking "engine or steering wheel?"

The Security Flip Side: Who Can Write to Your plists?

An emerald network graph around a central padlocked folder node with write-access links, two of which pulse warning red
Read access is harmless. Write access is the entire game. Guard the pen, not just the page.

Everything that makes Munki elegant also draws the security boundary in bright ink. If source catalog instructions are editable text files served off a web server, then the question that matters is not "is the format secure?" It is who can write to those files?

Walk the threat through. A manifest is a plist that tells a Mac what to install. An attacker who can edit a manifest, or drop a malicious pkginfo and rebuild the catalog, can instruct Macs within your SMB to install whatever they like, with the client's privileges, on every machine that reads that repo. The plain-text design that makes Munki so auditable for you makes it equally legible to anyone who gets write access. The pen is mightier than the page.

So the hardening checklist writes itself, and it is refreshingly concrete:

  • Serve over HTTPS, always. Plain HTTP means the non-encrypted instructions travel in the clear and can be tampered with in transit. TLS is non-negotiable.
  • Lock down write access to the repo. Reading the repo is harmless. Writing to it is total control. Keep the set of people and systems that can write to those plists as small as you can stand.
  • Authenticate the clients. Munki supports requiring credentials to fetch the repo, so it is not an open buffet for anyone who finds the URL.
  • Version-control everything. If a manifest changes, you want a commit that names who did it and when, not a mystery timestamp on a file.
  • Harden the web server itself. The repo is only as safe as the host serving it. Patch it, monitor it, and treat it like the sensitive infrastructure it quietly is.

None of this is exotic. It is the same web-server discipline our team preaches across every project, and you can read more of that playbook in our cybersecurity coverage and our secure web solutions guidance. The reassuring part is that securing Munki is not a mysterious art. It is web-server hygiene you may already know.

The mistake that turns elegance into an incident

The single most dangerous assumption is "it is just a static file server, so there is nothing to secure." That static file server is the command channel for every managed Mac in the building. Treat the repo's write permissions with the same seriousness you would treat a domain admin account, because functionally that is what they are.

Frequently Asked Questions

Does Munki use plist files?

Yes. Munki's repository data is built from Apple property-list (plist) files. Manifests and catalogs are stored as standard plist files in text format, and pkginfo files are also plist-formatted. The plist format is the backbone of how Munki describes and assigns software.

Is Munki an MDM?

No. Munki is software deployment and configuration management, not Mobile Device Management. It does not enroll devices, push profiles, or wipe and lock Macs. It is commonly run alongside an MDM, where the MDM handles enrollment and policy and Munki delivers the software catalog.

What kind of server does Munki need?

Just a plain web server. Per the project documentation, "a basic Munki server is simply a web server." It serves static files over HTTP or HTTPS, needs no database and no Munki tools installed on the server itself, and can even be hosted in the cloud.

Who created Munki?

Munki was lead-developed by Greg Neagle, a Staff Systems Engineer at Walt Disney Animation Studios, and released as open source by the studio. It is licensed under the Apache License 2.0.

Is Munki secure?

Munki is as secure as the web server and file permissions behind it. Because the control plane is editable plist files, the critical controls are serving over HTTPS, tightly restricting who can write to the repo, authenticating clients, and hardening the host. Read access is low risk; write access is effectively control over client installations and updates.

Key Takeaways

  • It really is just files: Munki manages a Mac clients with plain plist text files served by an ordinary web server, no database and no app server required.
  • Three plists run the show: pkginfo describes each item, catalogs index them, and manifests assign software per machine.
  • Not an MDM: Munki is the software catalog, commonly paired with an MDM that handles enrollment and policy.
  • Plain text is a superpower: the whole control plane is readable, diffable, and version-controllable like source code.
  • Write access is the whole security question: guard the people and systems that can write to the repo as if they were domain admins, because they effectively are.

It's Just Files All the Way Down

The genius of Munki is that it refuses to be clever. While the rest of the industry built sprawling platforms with databases and daemons, a systems engineer at an animation studio decided a whole shop could be run from a folder of text files on a web server, and was right. That plainness is what makes Munki so inspectable, so version-friendly, and so pleasantly hard to break. It is also what hands you the one job you cannot skip: decide exactly who is allowed to write to those files, then guard that list like it controls every Mac you own, because it does. Ready to harden the web server underneath it all? Bring us your repo and your worries, and let our cybersecurity team help you keep the elegant thing elegant.

Related Articles