Lab Server Setup
The lab server is a Raspberry Pi named engineering that serves a Munki
software repository to the lab Macs at http://engineering.local. Each lab Mac
checks that address about once an hour and installs whatever is listed for it.
This page rebuilds the server from a blank SD card to that working state.
The repository contents (installers, catalogs, and manifests) are not kept only on the Pi. The authoritative copy lives on the admin Mac (see Lab Software Update), and the last step on this page copies it back. A dead Pi loses nothing but an afternoon.
What You Need
- Raspberry Pi 4 or 5 with its power supply
- microSD card, 32 GB or larger (a USB SSD is better for the long run; see step 10)
- A Mac with Raspberry Pi Imager installed
- Lab Wi-Fi credentials, or an Ethernet cable to the lab VLAN (preferred)
- The admin Mac with
~/munki_repoon it, for the final step
How the Pieces Fit
| Where | What | Job |
|---|---|---|
| Admin Mac | ~/munki_repo and publish.sh |
The master copy; munkiimport adds software here |
Pi (engineering) |
nginx serving /srv/munki_repo |
Hands files to the lab Macs over plain HTTP |
| Pi | Avahi (Bonjour) | Answers to engineering.local without any DNS setup |
| Lab Macs | Munki client | Fetch http://engineering.local, install what's listed |
Munki needs nothing from a web server beyond answering GET requests for files,
so nginx with a one-line root directive is the whole server.
Image the SD Card
Steps are numbered continuously through this page so any step can be referred to by its number.
-
Open Raspberry Pi Imager on a Mac. Choose your Pi model, then for the operating system choose Raspberry Pi OS (other) ▸ Raspberry Pi OS Lite (64-bit). The server has no screen, so the desktop would only use space.
-
Choose the SD card as the storage, click Next, and choose Edit Settings when asked about OS customisation. Fill in the General tab:
Setting Value Hostname engineeringUsername piPassword choose one and record it where the other lab passwords live Configure wireless LAN the lab Wi-Fi SSID and password, country US(skip if wired)Locale time zone America/Phoenix, keyboardusOn the Services tab, enable SSH with password authentication. Save and write the card.
-
Insert the card, connect Ethernet if you have it, and power on. Give it two minutes for the first boot.
-
From any Mac on the lab network, confirm it's reachable and log in.
Your terminal should look like this: a
pi@engineering:~ $prompt. Ifpingcan't resolve the name, wait another minute and try again; if it never resolves, the Mac you're testing from isn't on the same network as the Pi.
mDNS Stays Inside One Network
engineering.local is a Bonjour name, and Bonjour does not cross between
VLANs. The Pi and the lab Macs must be on the same VLAN. A Mac on the staff
Wi-Fi will not see it, which is correct behavior, not a fault.
Install the Server Software
The remaining Pi steps run inside the SSH session from step 4.
-
Update the OS and install nginx, rsync, and Avahi (Avahi is normally present already; asking for it is harmless).
-
Confirm the hostname took, since everything else depends on it.
It should print
engineering. If it doesn't, runsudo hostnamectl set-hostname engineering, thensudo sed -i 's/127.0.1.1.*/127.0.1.1\tengineering/' /etc/hosts, andsudo systemctl restart avahi-daemon. -
Create the repository tree. It's owned by
pisorsyncfrom the admin Mac can write to it without root, and readable by everyone so nginx can serve it. -
Write the nginx site definition.
sudo tee /etc/nginx/sites-available/munki > /dev/null <<'NGINX' server { listen 80 default_server; listen [::]:80 default_server; server_name engineering.local engineering; root /srv/munki_repo; access_log /var/log/nginx/munki.access.log; error_log /var/log/nginx/munki.error.log; # Directory listings make the repo browsable while troubleshooting. autoindex on; # Large installers: let the kernel stream them rather than buffering. sendfile on; tcp_nopush on; location / { try_files $uri $uri/ =404; } } NGINXCatalogs, manifests, and pkginfo files have no file extension. nginx serves them as
application/octet-stream, which Munki is happy with; no MIME configuration is needed. -
Enable the site in place of nginx's default page and start it.
sudo rm -f /etc/nginx/sites-enabled/default sudo ln -sf /etc/nginx/sites-available/munki /etc/nginx/sites-enabled/munki sudo nginx -t && sudo systemctl reload nginx sudo systemctl enable nginx curl -I http://localhost/catalogs/Your terminal should look like this:
nginx -treportssyntax is okandtest is successful, andcurlreturnsHTTP/1.1 200 OK. -
Optional, recommended. If you have a USB SSD, use it for the repository instead of the SD card. SD cards wear out under the rewrites that every publish causes, and an SSD doesn't. Format it on the Pi, mount it at
/srv/munki_repo, add it to/etc/fstab, and repeat step 7. Nothing else on this page changes.
Give It a Fixed Address
engineering.local works whatever IP address the Pi gets, so this section is
insurance against a DHCP change stranding the clients, not a requirement.
-
Record both hardware addresses and send them to IT with a request for a DHCP reservation. Asking for both now means the Pi can be moved from Wi-Fi to Ethernet later without a second request.
-
Make sure the Wi-Fi address isn't being randomized, or the reservation will never match.
nmcli -g 802-11-wireless.cloned-mac-address connection show "$(nmcli -g NAME connection show --active | head -1)"Blank or
permanentis correct. If it printsrandomorstable, runsudo nmcli con mod "<connection name>" 802-11-wireless.cloned-mac-address permanentand reconnect. -
Wire the Pi when you can. A 3.8 GB Fusion installer over gigabit Ethernet reaches a lab Mac in under a minute; over 2.4 GHz Wi-Fi it's a long afternoon.
Restore the Repository
These steps run on the admin Mac. They assume it is already set up per Lab Software Update; if both machines died at once, set up the admin Mac first and come back here.
-
Give the admin Mac passwordless SSH to the Pi, so publishing never prompts.
The second command should print
okwith no password prompt. -
Publish the repository. This copies everything in
~/munki_repoto the Pi and sets permissions nginx can read.Expect the first publish to take a while if it includes Fusion; the pkg is 3.8 GB.
-
Verify from the outside, on any Mac on the lab VLAN.
curl -s http://engineering.local/manifests/site_default curl -sI http://engineering.local/catalogs/production | head -1Your terminal should look like this: the manifest prints as a plist, and the catalog returns
200 OK. On any enrolled lab Mac,sudo managedsoftwareupdate --checkonlywill now talk to the new server with no client-side changes, because the address hasn't changed.
Done
The server is back. Lab Macs pick it up on their next hourly check.
Keeping It Running
- Updates. Every few months,
ssh pi@engineering.localand runsudo apt update && sudo apt full-upgrade -y && sudo reboot. Pick a time when the lab is empty; the reboot takes about a minute. - Disk space.
df -h /srv/munki_repoon the Pi. Pruning old versions happens on the admin Mac withrepoclean(see Lab Software Update), and the next publish removes them from the Pi. - Logs.
/var/log/nginx/munki.access.logshows every request a lab Mac made.sudo grep ' 404 ' /var/log/nginx/munki.access.log | tailis the first thing to look at when a client complains. - If it stops responding. Power-cycle it. There is no state on the Pi that isn't also on the admin Mac, so the worst case is this page from step 1.