nanomdm
NanoMDM Apple MDM Server (v0.9.x)
You are an expert at building and operating Apple MDM solutions with NanoMDM. This skill references the NanoMDM v0.9.x source code and documentation from github.com/micromdm/nanomdm.
Core Principles
- Minimalist composable architecture -- NanoMDM is a thin layer between HTTP handlers, a service interface layer, and storage abstractions. Each layer is independently composable.
- Middleware chain pattern -- Services implement
CheckinAndCommandServiceand wrap each other:dump -> certauth -> multi(nanomdm, webhook). The first service inmultireturns values; others run in parallel as fire-and-forget. - Enrollment ID normalization -- All enrollment types (device UDID, User Enrollment, Shared iPad) are collapsed into a single string ID. Device channel:
UUID. User channel:UUID:UUID. Shared iPad:UUID:ShortName. - Storage interface driven -- Storage is defined by Go interfaces (
ServiceStore,PushStore,PushCertStore,CommandEnqueuer,CertAuthStore). Multiple backends implement these interfaces. - Raw Plist commands -- Commands are submitted as raw Apple Plist XML, not JSON. Use the
cmdr.pytool or construct plists directly. - Certificate-based authentication -- Device identity certificates are validated against CA certs. The
certauthservice middleware associates and verifies cert hashes per enrollment.
How to Use This Skill
Before generating code, load the relevant reference file(s):
- Architecture & service interfaces:
cat references/architecture.md - Storage backends & schemas:
cat references/storage.md - HTTP API & endpoints:
cat references/http-api.md - Configuration & CLI flags:
cat references/configuration.md - MDM protocol types & check-in handling:
cat references/mdm-protocol.md
Quick Reference
Module Path & Dependencies
module github.com/micromdm/nanomdm
go 1.18
Key dependencies: github.com/micromdm/nanolib, github.com/micromdm/plist, github.com/go-sql-driver/mysql, github.com/lib/pq, github.com/smallstep/pkcs7, github.com/peterbourgon/diskv/v3
Core Service Interface
// CheckinAndCommandService is the main composable interface
type CheckinAndCommandService interface {
Checkin // Authenticate, TokenUpdate, CheckOut, SetBootstrapToken, GetBootstrapToken, UserAuthenticate, DeclarativeManagement, GetToken
CommandAndReportResults // CommandAndReportResults(r, results) (*Command, error)
}
Service Middleware Chain (default cmd/nanomdm setup)
HTTP Request
-> cert extraction (Mdm-Signature header or -cert-header)
-> cert verification (CA pool)
-> dump (optional, -dump flag)
-> certauth (certificate-enrollment association)
-> multi [nanomdm service, webhook service]
-> nanomdm dispatches to storage
-> webhook sends HTTP callbacks
Storage Backends
| Backend | Flag | DSN Example | Notes |
|---|---|---|---|
| filekv | -storage filekv |
-storage-dsn dbkv |
Default. Uses diskv package internally. Zero deps. |
| mysql | -storage mysql |
-storage-dsn user:pass/dbname |
MySQL 8.0.19+. Run schema.sql first. |
| pgsql | -storage pgsql |
-storage-dsn postgres://user:pass@host/db |
PostgreSQL 9.5+. Run schema.sql first. |
| inmem | -storage inmem |
(none) | Volatile in-memory. All data lost on exit. |
| file | -storage file |
-storage-dsn /path/to/db |
Deprecated. Requires -storage-options enable_deprecated=1. |
| multi | Multiple -storage flags |
First backend is authoritative; others are write-only. |
Note: There is no
-storage diskvCLI option. Thefilekvbackend uses thediskvGo package internally. Theinmembackend also uses the sharedkvpackage with in-memory buckets.
HTTP API Endpoints
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/mdm |
PUT | Cert | MDM check-in and command reports (primary) |
/checkin |
PUT | Cert | Separate check-in endpoint (if -checkin flag) |
/v1/pushcert |
PUT | API key | Upload APNs push cert+key (PEM concatenated) |
/v1/push/{id,...} |
GET | API key | Send APNs push to enrollment ID(s) |
/v1/enqueue/{id,...} |
PUT | API key | Enqueue raw plist command. ?nopush=1 to skip push. |
/v1/escrowkeyunlock |
POST | API key | Activation Lock bypass via Apple API |
/migration |
PUT | API key | Enrollment migration endpoint (if -migration flag) |
/version |
GET | None | Server version JSON |
/authproxy/ |
* | Cert | Reverse proxy with MDM cert auth (if -auth-proxy-url) |
Webhook Event Topics
mdm.Authenticate, mdm.TokenUpdate, mdm.CheckOut, mdm.Connect, mdm.UserAuthenticate, mdm.SetBootstrapToken, mdm.GetBootstrapToken, mdm.DeclarativeManagement, mdm.GetToken
Enrollment Types
const (
Device = 1 + iota // macOS UDID, iOS UDID
User // macOS UserID (UDID:UserID)
UserEnrollmentDevice // iOS EnrollmentID (BYOD)
UserEnrollment // iOS EnrollmentUserID
SharediPad // Shared iPad (UDID:UserShortName)
)
Common Operations
# Upload push certificate
cat push.pem push.key | curl -T - -u nanomdm:APIKEY 'http://host:9000/v1/pushcert'
# Send push notification
curl -u nanomdm:APIKEY 'http://host:9000/v1/push/ENROLLMENT-ID'
# Enqueue command
./cmdr.py SecurityInfo | curl -T - -u nanomdm:APIKEY 'http://host:9000/v1/enqueue/ENROLLMENT-ID'
# Enqueue without push
./cmdr.py ProfileList | curl -T - -u nanomdm:APIKEY 'http://host:9000/v1/enqueue/ENROLLMENT-ID?nopush=1'
# Multi-target push/enqueue (comma-separated IDs)
curl -u nanomdm:APIKEY 'http://host:9000/v1/push/ID1,ID2,ID3'
Docker
docker pull ghcr.io/micromdm/nanomdm:latest
docker run ghcr.io/micromdm/nanomdm:latest -ca /path/to/ca.pem -api APIKEY
Building from Source
make # builds for current OS/arch
make release # cross-compile all platforms
make test # run tests