Secure Munki server with Let's Encrypt and SCEP

5 minutes

In this post, I will show you how to set up a public Munki repository. The server will be configured to use HTTPS, but also require clients that connect to provide an X.509 client certificate to access the repo. Normally, this kind of setup would require your organization to pay for a SSL certificate, and set up a PKI system that will sign unique certificates for each device. Some enterprising MacAdmins have used the puppet CA to issue certificates for each Mac, but if you’re not already using puppet, this option is less attractive. Today, I will show you how to configure a secure server, without any cost, and with very little technical knowledge necessary.

First, let’s cover the technologies we’ll use today:

Important Note

Both the SCEP tools and squirrel are in preview. Over the next coming months I will be adding more features and fixing bugs. Please this treat this tutorial as a demo as well.


Now that we’ve covered the technologies used, let’s deploy our Munki server.
First, let’s get the SCEP tools. You can download the latest version here. We’ll be deploying the scepclient tool on every Mac, but we only need the server to create a CA.

scepserver ca -init -organization groob-io

The above command creates a CA that we will use to sign and validate client certificates. The tool will create a new folder called depot with a private key and CA cert:

├── ca.key
└── ca.pem

Our devices will all need to trust this CA. There are two ways to do it. One is to add it to a profile and install the profile on each device. The second way is by adding the CA as a trusted root on each device. We’ll handle that in the munki preflight script.

Now, let’s configure our server. Caddy uses a configuration file named Caddyfile by convention, so that’s what we’ll call ours.

# Caddyfile
# See all valid configuration options here: https://caddyserver.com/docs/getting-started

# SCEP server configuration
# Note that the port for SCEP must be different from the server. 
# We use :2016, but any valid port will do.
https://scep.groob.io:2016 {
    # The email is necessary for LE to send us expiration reminders
    tls groob@gmail.com
    # SCEP server configuration. 
    # Depot is the path to the depot folder we created earlier.
    # The challenge is a preshared password used by your server to validate requests from the client. 
    # Only clients that use the same challenge will be granted a certificate.
    scep {
        depot depot
        challenge secret

# munki repo config
https://munki.groob.io {
    # same email here
    # also configure the server to request client certificates and validate them with the CA.
    tls groob@gmail.com {
        clients require depot/ca.pem
    # set the root of your munki repo
    root /path/to/munki/repo
    browse /

Start the squirrel server.

# -agree is required for configuring LE
squirrel -agree -conf=/path/to/your/Caddyfile

The server will start up and serve your Munki repo. If you try to navigate to it in the browser, you’ll be denied access. Our munki repo is secure.
Now, let’s request client certificates, and enable our devices to connect to the repo. We’ll do these steps manually here, but you can automate these steps later.

# create the certs directory
sudo mkdir -p /Library/Managed\ Installs/certs/
# copy CA cert we created in the beggining to certs directory
sudo cp ca.pem /Library/Managed\ Installs/certs/
# create a private key and request a new certificate
sudo scepclient -private-key /Library/Managed\ Installs/certs/client.key -server-url=https://scep.groob.io:2016/scep -challenge=secret -cn=munki-client

# configure munki preferences
sudo defaults write /Library/Preferences/ManagedInstalls.plist ClientKeyPath "/Library/Managed Installs/certs/client.key"
sudo defaults write /Library/Preferences/ManagedInstalls.plist UseClientCertificate -bool true

# check that it's working
sudo managedsoftwareupdate -vvvv --checkonly --munkipkgsonly

Congratulations, you set up a secure Munki repo that only your munki clients can access.

If you’re interested in the development of SCEP, Squirrel and MDM join me in the #micromdm channel on the MacAdmins Slack Team, and of course, report any issues or feature requests on the github page.