<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Focused Systems</title><link>https://focused-systems.pages.dev/</link><description>Exploring modern cloud workflows. DevOps, APIs, Git, serverless architectures, pipelines, and software integrations, alongside personal tech solutions.</description><language>en</language><generator>Hugo</generator><image><url>https://focused-systems.pages.dev/images/social.png</url><title>Focused Systems</title><link>https://focused-systems.pages.dev/</link></image><lastBuildDate>Thu, 12 Jun 2025 17:31:28 +0000</lastBuildDate><atom:link href="https://focused-systems.pages.dev/tags/munki/index.xml" rel="self" type="application/rss+xml"/><item><title>Modern Munki DevOps</title><link>https://focused-systems.pages.dev/munki-devops/</link><guid isPermaLink="true">https://focused-systems.pages.dev/munki-devops/</guid><pubDate>Thu, 12 Jun 2025 17:31:28 +0000</pubDate><dc:creator>Rod Christiansen</dc:creator><category>devops</category><category>git</category><category>ci/cd</category><category>munki</category><category>azure</category><category>macadmin</category><description>How we transformed our Munki workflow into a DevOps-native system using Git, CI/CD pipelines, and Azure. Companion post to my MacDevOps YVR 2025 talk.</description><content:encoded><![CDATA[<blockquote><strong>MacDevOps YVR 2025 Companion Post</strong></blockquote><p>A year ago, we were managing Macs the way most orgs still do: one shared Mac, VNC&#x2019;d into, running a local copy of Munki with no real version control or workflow isolation. Git was an afterthought. Deployments were manual. It worked&#x2014;until it didn&#x2019;t scale.</p><p>We&#x2019;ve since inverted the model. Git is the gate. CI is the deployer. Each admin works from their own machine. And the Munki repo is fully DevOps-native.</p><p>Here&#x2019;s how we rebuilt everything using Git, Azure DevOps, Service Bus, pipelines, local caching servers, and inventory automation&#x2014;all open source and cloud-integrated.</p><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://blog.focused.systems/content/files/2025/06/MunkiDevOps-1.pdf" title="Download" download><div class="kg-file-card-contents"><div class="kg-file-card-title">MunkiDevOps Presentation Slides</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">MunkiDevOps.pdf</div><div class="kg-file-card-filesize">89 MB</div></div></div><div class="kg-file-card-icon"><svg viewbox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"/><line class="a" x1="12" y1="6.75" x2="12" y2="18"/><circle class="a" cx="12" cy="12" r="11.25"/></svg></div></a></div><h2 id="from-manual-to-devops">From Manual to DevOps</h2><p>The legacy flow was:</p><ul><li>GitLab running on-prem</li><li>One shared Mac as the deploy point</li><li>One central repo, updated by many hands</li><li>No pipeline. No hooks. No approval gates.</li><li>Everyone stepped on everyone&#x2019;s toes</li></ul><p>Now we have:</p><ul><li>Azure DevOps Git repos and pipelines</li><li>Git hooks that upload/download packages automatically</li><li>Separate working copies per admin</li><li>Local caching servers that sync intelligently</li><li>A full CI/CD system that integrates with inventory and deploys via pull requests</li></ul><h2 id="architecture-overview">Architecture Overview</h2><p>We&#x2019;ve split this into two core flows:</p><h3 id="munki-devops-infrastructure">Munki DevOps Infrastructure</h3><ul><li>Admins commit to a shared Azure DevOps repo with <code>manifests/</code> and <code>pkgsinfo/</code></li><li>Git hooks (post-commit/merge) run <code>azcopy sync</code> to upload or download packages</li><li>A pipeline (<code>munki-push-production.yml</code>) builds catalogs and updates Azure Storage</li><li>Local caching servers (like PLUTO and PROTEUS) are notified via Azure Service Bus</li><li>A daemon listens for commits and runs <code>git pull</code> and syncs assets</li><li>CDN serves files globally or from on-prem caches</li><li>It&#x2019;s fast, redundant, and observable</li></ul><h3 id="inventory-orchestrated-enrollment">Inventory-Orchestrated Enrollment</h3><ul><li>A polling script checks Snipe-IT for inventory changes and builds new CSVs</li><li>CSVs are committed to Git &#x2192; triggers DevOps pipelines &#x2192; runs <code>enrollment-munki</code>, <code>enrollment-intune</code>, <code>enrollment-sharepoint</code>, and more</li><li>Each system (Munki, Intune, Fleet, TDX, Papercut) gets updated data</li><li>Pull requests are the approval gate</li><li>Everything is traceable, auditable, and CI-driven</li></ul><h2 id="resources">Resources</h2><ul><li><strong>Presentation Repo</strong>: <a href="https://github.com/rodchristiansen/munki-devops">github.com/rodchristiansen/munki-devops</a></li></ul><p>Want to talk shop or ask questions? Connect with me on <a href="https://bsky.app/profile/rodchristiansen.net">BlueSky</a> or on the <a href="https://github.com/rodchristiansen">GitHub</a>.</p>
]]></content:encoded></item></channel></rss>