### NanoMDM Server Setup and API Key Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Instructions on how to start the NanoMDM server with CA certificate and API key configuration. ```APIDOC ## Run NanoMDM server NanoMDM requires the `-ca` switch for authenticating MDM clients using their device identity certificates against the provided CA certificate. The `-api` switch enables API functionality and sets an API key. ### Command Example ```bash ./nanomdm-darwin-amd64 -ca ca.pem -api nanomdm -debug ``` ### Default Behavior By default, the file storage backend writes enrollment data into a directory named `db`. ### API Key Authentication API keys function as passwords for HTTP Basic Authentication, with the username set to `nanomdm`. This means proxies may have access to API authentication credentials. ``` -------------------------------- ### Enrollment Migration Example Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Example usage of the nano2nano tool for migrating enrollment data. This command initiates a migration from a file storage backend to a specified URL, with debug logging enabled. ```bash $ ./nano2nano-darwin-amd64 -storage file -storage-dsn db -url 'http://127.0.0.1:9010/migration' -key nanomdm -debug 2021/06/04 14:29:54 level=info msg=storage setup storage=file 2021/06/04 14:29:54 level=info checkin=Authenticate device_id=99385AF6-44CB-5621-A678-A321F4D9A2C8 type=Device 2021/06/04 14:29:54 level=info checkin=TokenUpdate device_id=99385AF6-44CB-5621-A678-A321F4D9A2C8 type=Device ``` -------------------------------- ### Start NanoMDM Server with Webhook Integration Source: https://context7.com/micromdm/nanomdm/llms.txt Enable webhook callbacks for MDM events by starting the server with the '-webhook-url' and '-webhook-hmac-key' flags. The webhook format is compatible with MicroMDM. ```bash ./nanomdm \ -ca /path/to/ca.pem \ -api nanomdm \ -webhook-url "https://your-server.example.com/webhook" \ -webhook-hmac-key "your-secret-key" \ -debug ``` -------------------------------- ### Start NanoMDM Server with Migration Endpoint Enabled Source: https://context7.com/micromdm/nanomdm/llms.txt Enable the migration endpoint when starting the NanoMDM server. This is necessary for migrating MDM enrollments. ```bash ./nanomdm -ca /path/to/ca.pem -api nanomdm -migration -debug ``` -------------------------------- ### Build from Source with Go Toolchain Source: https://github.com/micromdm/nanomdm/blob/main/README.md If you have a Go toolchain installed, you can checkout the source code and build NanoMDM using the make command. ```bash make ``` -------------------------------- ### Enable Authentication Proxy for DDM Assets Source: https://context7.com/micromdm/nanomdm/llms.txt Command-line arguments to start NanoMDM with an authentication proxy for retrieving Declarative Device Management assets. Requires bash. ```bash # Start server with authentication proxy ./nanomdm \ -ca /path/to/ca.pem \ -api nanomdm \ -auth-proxy-url "http://localhost:8080" \ -debug # Requests to /authproxy/* are authenticated using MDM device certificates # then proxied to the target URL with enrollment info headers: # # Request: GET /authproxy/assets/config.json # Proxied to: http://localhost:8080/assets/config.json # Headers added: # X-Enrollment-ID: 99385AF6-44CB-5621-A678-A321F4D9A2C8 # X-Trace-ID: abc123def456 ``` -------------------------------- ### Run NanoMDM Server with File Storage Source: https://context7.com/micromdm/nanomdm/llms.txt Starts the NanoMDM server using file-based storage and enables the API. Use the -debug flag for verbose logging. ```bash ./nanomdm -ca /path/to/ca.pem -api nanomdm -debug ``` -------------------------------- ### Configure NanoMDM for DDM Forwarding Source: https://context7.com/micromdm/nanomdm/llms.txt Command-line arguments to start NanoMDM and forward Declarative Management requests to an external DDM server. Requires bash. ```bash # Start NanoMDM with DDM forwarding ./nanomdm \ -ca /path/to/ca.pem \ -api nanomdm \ -dm "https://ddm.example.com/v1/" \ -dm-send-hmac-key "outgoing-secret" \ -dm-recv-hmac-key "incoming-secret" \ -debug # DDM requests are forwarded with: # - X-Enrollment-ID header containing the NanoMDM enrollment ID # - X-Hmac-Signature header with Base64-encoded SHA-256 HMAC (if configured) # # Endpoints called: # - https://ddm.example.com/v1/declaration-items # - https://ddm.example.com/v1/status # - https://ddm.example.com/v1/tokens # - https://ddm.example.com/v1/declaration/... ``` -------------------------------- ### Full Production NanoMDM Server Setup Source: https://context7.com/micromdm/nanomdm/llms.txt A comprehensive configuration for a production NanoMDM server, including intermediate certificates, a custom API key, MySQL storage, webhook integration, and Declarative Management support. ```bash ./nanomdm \ -ca /path/to/ca.pem \ -intermediate /path/to/intermediate.pem \ -api your-secret-api-key \ -storage mysql \ -storage-dsn "nanomdm:password@tcp(db.example.com:3306)/nanomdm" \ -webhook-url "https://your-app.example.com/mdm-webhook" \ -webhook-hmac-key "your-webhook-secret" \ -dm "https://ddm.example.com/v1/" \ -listen :9000 ``` -------------------------------- ### Run ngrok for NanoMDM Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Start an ngrok tunnel to expose the NanoMDM server running on port 9000 to the internet. This provides public forwarding addresses for external access. ```bash $ ./ngrok http 9000 ngrok by @inconshreveable (Ctrl+C to quit) Session Status online Session Expires 1 hour, 59 minutes Version 2.3.40 Region United States (us) Web Interface http://127.0.0.1:4041 Forwarding http://625ae9460120.ngrok.io -> http://localhost:9000 Forwarding https://625ae9460120.ngrok.io -> http://localhost:9000 [snip] ``` -------------------------------- ### GET /version Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Retrieves the version of the running NanoMDM server. ```APIDOC ## GET /version ### Description Returns a JSON response containing the version information of the currently running NanoMDM server. ### Method GET ### Endpoint `/version` ### Response #### Success Response (200) - **version** (string) - The version string of the NanoMDM server. #### Response Example ```json { "version": "1.2.3" } ``` ``` -------------------------------- ### Migrate Storage using nano2nano Tool Source: https://context7.com/micromdm/nanomdm/llms.txt Use the nano2nano tool to migrate MDM enrollments from one storage backend to another, for example, from file storage to MySQL. Requires specifying storage types and data source names. ```bash ./nano2nano \ -storage file \ -storage-dsn /path/to/old/db \ -url 'http://127.0.0.1:9000/migration' \ -key nanomdm \ -debug ``` -------------------------------- ### Run SCEP Server Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Start the SCEP server, listening on port 8080 by default. Use the -port switch to change the listening port if necessary. The -allowrenew 0 flag disables renewal, and -debug enables verbose logging. ```bash ./scepserver-darwin-amd64 -allowrenew 0 -challenge nanomdm -debug level=info ts=2021-05-29T21:19:40.902041Z caller=scepserver.go:163 transport=http address=:8080 msg=listening ``` -------------------------------- ### Get NanoMDM Server Version Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Access the `/version` endpoint to retrieve a JSON response containing the version of the running NanoMDM server. ```bash # Example usage for version endpoint (conceptual, actual command not provided in source) # curl -u nanomdm:nanomdm http://127.0.0.1:9000/version ``` -------------------------------- ### Initialize NanoMDM Go Service Source: https://context7.com/micromdm/nanomdm/llms.txt Demonstrates initializing the NanoMDM service with MySQL storage and setting up HTTP handlers for MDM and API endpoints. Requires Go. ```go package main import ( "context" "log" "net/http" "github.com/micromdm/nanomdm/mdm" "github.com/micromdm/nanomdm/service" "github.com/micromdm/nanomdm/service/nanomdm" "github.com/micromdm/nanomdm/storage/mysql" httpmdm "github.com/micromdm/nanomdm/http/mdm" httpapi "github.com/micromdm/nanomdm/http/api" "github.com/micromdm/nanomdm/push/nanopush" pushsvc "github.com/micromdm/nanomdm/push/service" "github.com/micromdm/nanolib/log/stdlogfmt" ) func main() { logger := stdlogfmt.New() // Initialize MySQL storage storage, err := mysql.New( mysql.WithDSN("nanomdm:password@tcp(localhost:3306)/nanomdm"), mysql.WithLogger(logger), ) if err != nil { log.Fatal(err) } // Create the core NanoMDM service mdmService := nanomdm.New(storage, nanomdm.WithLogger(logger.With("service", "nanomdm")), ) // Setup push service pushFactory := nanopush.NewFactory() pushService := pushsvc.New(storage, storage, pushFactory, logger) // Setup HTTP handlers mux := http.NewServeMux() // MDM endpoint for device communication mux.Handle("/mdm", httpmdm.CheckinAndCommandHandler(mdmService, logger)) // API endpoints (with authentication middleware) httpapi.HandleAPIv1("/v1", mux, logger, storage, pushService) log.Println("Starting server on :9000") log.Fatal(http.ListenAndServe(":9000", mux)) } // Custom service implementation example type CustomService struct { service.CheckinAndCommandService logger log.Logger } func (s *CustomService) Authenticate(r *mdm.Request, msg *mdm.Authenticate) error { s.logger.Info("msg", "device authenticated", "udid", msg.UDID, "serial", msg.SerialNumber, "model", msg.Model) return s.CheckinAndCommandService.Authenticate(r, msg) } func (s *CustomService) TokenUpdate(r *mdm.Request, msg *mdm.TokenUpdate) error { s.logger.Info("msg", "token update received", "enrollment_id", r.ID) return s.CheckinAndCommandService.TokenUpdate(r, msg) } ``` -------------------------------- ### Run NanoMDM Server with Environment Variables Source: https://context7.com/micromdm/nanomdm/llms.txt Demonstrates configuring the NanoMDM server using environment variables. Ensure variables are prefixed with NANOMDM_. ```bash export NANOMDM_STORAGE=mysql export NANOMDM_STORAGE_DSN="nanomdm:password@tcp(localhost:3306)/nanomdm" export NANOMDM_API=nanomdm export NANOMDM_CA=/path/to/ca.pem ./nanomdm ``` -------------------------------- ### Initialize MySQL Database Schema for NanoMDM Source: https://context7.com/micromdm/nanomdm/llms.txt Use these SQL commands to create the database, user, and grant privileges for NanoMDM. Apply the schema from storage/mysql/schema.sql afterwards. ```sql -- Create database and user CREATE DATABASE nanomdm CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'nanomdm'@'%' IDENTIFIED BY 'your-secure-password'; GRANT ALL PRIVILEGES ON nanomdm.* TO 'nanomdm'@'%'; FLUSH PRIVILEGES; ``` ```sql -- Apply schema (from storage/mysql/schema.sql) USE nanomdm; ``` ```sql -- Example: Query enrolled devices SELECT id, serial_number, created_at FROM devices; ``` ```sql -- Example: View command queue for an enrollment SELECT * FROM view_queue WHERE id = '99385AF6-44CB-5621-A678-A321F4D9A2C8'; ``` ```sql -- Example: Check push certificate expiry SELECT topic, DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(updated_at)), '%Y-%m-%d') as uploaded, stale_token FROM push_certs; ``` -------------------------------- ### Download, Extract, and Initialize SCEP Server Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Download the SCEP server binary, extract it, and initialize a new Certificate Authority (CA). The CA and issuance data will be stored in a 'depot' directory by default. ```bash $ mkdir scep && cd scep $ curl -RLO https://github.com/micromdm/scep/releases/download/v2.1.0/scepserver-darwin-amd64-v2.1.0.zip [snip] $ unzip scepserver-darwin-amd64-v2.1.0.zip Archive: scepserver-darwin-amd64-v2.1.0.zip inflating: scepserver-darwin-amd64 $ ./scepserver-darwin-amd64 ca -init Initializing new CA ``` -------------------------------- ### Authentication Proxy Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Reverse proxies requests starting with /authproxy/ to a specified target URL, authenticating them using MDM protocols. Useful for secure content retrieval, especially for Declarative Device Management. ```APIDOC ## Authentication Proxy ### Description Requests to URLs starting with `/authproxy/` are reverse-proxied to a target URL specified by the `-auth-proxy-url` flag. This endpoint authenticates incoming requests using the same MDM authentication mechanisms as other endpoints (e.g., Check-In, Command Report), supporting both TLS client configuration and certificate headers. This feature is particularly useful for Declarative Device Management, enabling certain Asset declarations to use MDM authentication for content retrieval. ### Method GET, POST, PUT, DELETE, etc. (Depends on the proxied request) ### Endpoint `/authproxy/*` ### Parameters #### Query Parameters - **(None explicitly defined for the proxy itself, but proxied requests may have them)** #### Request Body - **(None explicitly defined for the proxy itself, but proxied requests may have them)** ### Request Example If the server receives a request at `/authproxy/foo/bar` and the `-auth-proxy-url` is set to `http://[::1]:9008`, NanoMDM will proxy the request to `http://[::1]:9008/foo/bar`. ### Response #### Success Response (200) - **(Content of the proxied response)** #### Error Response - **502 Bad Gateway**: Returned for any issues encountered during the proxying process. ``` -------------------------------- ### POST /v1/enqueue/ Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Queues MDM commands to be sent to enrollments. Accepts a raw Plist command in the request body. ```APIDOC ## POST /v1/enqueue/ ### Description Allows sending of MDM commands to enrollments. It takes a raw command Plist input as the HTTP body. The command is associated with the enrollment ID(s) provided in the URL path. ### Method POST ### Endpoint `/v1/enqueue/{enrollment_ids}` ### Parameters #### Path Parameters - **enrollment_ids** (string) - Required - A comma-separated list of enrollment IDs (UDIDs) to send commands to. - **nopush** (boolean) - Optional - If set to `1`, skips sending the push notification request to the device. #### Request Body - **command_plist** (string) - Required - The raw Plist XML representing the MDM command. ### Request Example ```bash ./cmdr.py -r | curl -T - -u nanomdm:nanomm 'http://127.0.0.1:9000/v1/enqueue/E9085AF6-DCCB-5661-A678-BCE8F4D9A2C8' ``` ### Response #### Success Response (200) - **status** (object) - Contains the push result for each enrollment ID. - **{enrollment_id}** (object) - Details for a specific enrollment. - **push_result** (string) - A UUID representing the result of the push operation. - **command_uuid** (string) - The unique identifier for the queued command. - **request_type** (string) - The type of MDM command that was enqueued. - **no_push** (boolean) - Indicates if the push notification was skipped (only present if `nopush=1` was used). #### Response Example ```json { "status": { "E9085AF6-DCCB-5661-A678-BCE8F4D9A2C8": { "push_result": "16C80450-B79F-E23B-F99B-0810179F244E" } }, "command_uuid": "1ec2a267-1b32-4843-8ba0-2b06e80565c4", "request_type": "ProfileList" } ``` ``` -------------------------------- ### Retrieve APNS Push Certificate Information using curl Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Retrieve the topic and expiry date of a stored APNS push certificate by sending a GET request to the /v1/pushcert endpoint with the 'topic' query parameter. This avoids re-uploading the certificate. ```bash $ curl -u nanomdm:nanomdm 'http://127.0.0.1:9000/v1/pushcert?topic=com.apple.mgmt.External.e3b8ceac-1f18-2c8e-8a63-dd17d99435d9' { "topic": "com.apple.mgmt.External.e3b8ceac-1f18-2c8e-8a63-dd17d99435d9", "not_after": "2026-01-07T04:04:46Z" } ``` -------------------------------- ### Run NanoMDM Server with PostgreSQL and Command Deletion Source: https://context7.com/micromdm/nanomdm/llms.txt Sets up the NanoMDM server with PostgreSQL storage and enables automatic command deletion. The -storage-options flag is used to configure specific backend options. ```bash ./nanomdm \ -ca /path/to/ca.pem \ -api nanomdm \ -storage pgsql \ -storage-dsn "postgres://user:pass@localhost:5432/nanomdm" \ -storage-options "delete=1" \ -debug ``` -------------------------------- ### Storage Backends Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Configuration options for different storage backends. ```APIDOC ## Storage Backends ### In-Memory Storage Backend * `-storage inmem` Configure the `inmem` in-memory storage backend. This manages enrollment and command queue data entirely in *volatile* memory. There are no options and the DSN is ignored. > [!CAUTION] > All data is lost when the server process exits when using the in-memory storage backend. *Example:* `-storage inmem` ### Multi-Storage Backend You can configure multiple storage backends to be used simultaneously. Specifying multiple sets of `-storage`, `-storage-dsn`, & `-storage-options` flags will configure the "multi-storage" adapter. The flags must be specified in sets and are related to each other in the order they're specified: for example the first `-storage` flag corresponds to the first `-storage-dsn` flag and so forth. Note that empty options must be specified even if the backend is not using them. Be aware that only the first storage backend will be "used" when interacting with the system, all other storage backends are called to, but any *results* are discarded. In other words consider them write-only. Also beware that you will have very bizarre results if you change to using multiple storage backends in the midst of existing enrollments. You will receive errors about missing database rows or data. A storage backend needs to be around when a device (or all devices) initially enroll(s). There is no "sync" or backfill system with multiple storage backends (see the migration ability if you need this). The multi-storage backend is only really useful if you've always been using multiple storage backends or if you're doing some type of development or testing (perhaps creating a new storage backend). For example to use both a `filekv` *and* `mysql` backend your command line might look like: `-storage filekv -storage-dsn dbkv -storage mysql -storage-dsn nanomdm:nanomdm/mymdmdb`. You can also mix and match backends, or multiple of the same backend. Behavior is undefined (and probably very bad) if you specify two backends of the same type with the same DSN (i.e. sharing the same data source). ``` -------------------------------- ### POST /migration Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Establishes an enrollment by sending raw `TokenUpdate` and `Authenticate` messages. This endpoint bypasses certificate validation and authentication. ```APIDOC ## POST /migration ### Description Allows establishing an MDM enrollment by sending raw `TokenUpdate` and `Authenticate` messages. This endpoint bypasses certificate validation and authentication, facilitating the migration of existing MDM enrollments. ### Method POST ### Endpoint `/migration` ### Parameters #### Request Body - **message** (object) - Required - The raw `TokenUpdate` or `Authenticate` message payload. ### Request Example ```bash # Example using llorne tool (from micro2nano project) # curl -X POST -d @enrollment.json --cacert ca.crt --cert client.crt --key client.key https://your-mdm.com/migration ``` ### Response #### Success Response (200) - **status** (string) - Indicates the success or failure of the migration operation. #### Response Example ```json { "status": "success" } ``` ``` -------------------------------- ### Run NanoMDM Server Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Execute the NanoMDM server with CA certificate for client authentication and API key for enabling API functionality. Debug mode is enabled for verbose logging. The file storage backend defaults to a 'db' directory. ```bash ./nanomdm-darwin-amd64 -ca ca.pem -api nanomdm -debug 2021/05/29 14:33:04 level=info msg=storage setup storage=file 2021/05/29 14:33:04 level=info msg=starting server listen=:9000 ``` -------------------------------- ### Run NanoMDM Server with MySQL Storage Source: https://context7.com/micromdm/nanomdm/llms.txt Configures the NanoMDM server to use MySQL as the storage backend. Specify the data source name (DSN) and the listening port. ```bash ./nanomdm \ -ca /path/to/ca.pem \ -api nanomdm \ -storage mysql \ -storage-dsn "nanomdm:password@tcp(localhost:3306)/nanomdm" \ -listen :9000 \ -debug ``` -------------------------------- ### Download and Extract NanoMDM Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Download the NanoMDM binary for macOS (amd64 architecture) and extract the executable file. ```bash $ mkdir nanomdm && cd nanomdm $ curl -RLO https://github.com/micromdm/nanomdm/releases/download/v0.2.0/nanomdm-darwin-amd64-v0.2.0.zip [snip] $ unzip nanomdm-darwin-amd64-v0.2.0.zip Archive: nanomdm-darwin-amd64-v0.2.0.zip inflating: nanomdm-darwin-amd64 ``` -------------------------------- ### NanoMDM Client Check-in and Command Processing Logs Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md These logs illustrate the client checking in with the server, retrieving and processing a command, and then acknowledging its completion. The final log indicates no further commands are available for the client. ```log 2021/05/30 12:46:40 level=info handler=log addr=::1 method=PUT path=/mdm agent=MDM-OSX/1.0 mdmclient/1090 real_ip=1.2.3.4 2021/05/30 12:46:40 level=info service=nanomdm status=Idle id=99385AF6-44CB-5621-A678-A321F4D9A2C8 type=Device 2021/05/30 12:46:40 level=debug service=nanomdm msg=command retrieved id=99385AF6-44CB-5621-A678-A321F4D9A2C8 command_uuid=1ec2a267-1b32-4843-8ba0-2b06e80565c4 2021/05/30 12:46:40 level=info handler=log addr=::1 method=PUT path=/mdm agent=MDM-OSX/1.0 mdmclient/1090 real_ip=1.2.3.4 2021/05/30 12:46:40 level=info service=nanomdm status=Acknowledged id=99385AF6-44CB-5621-A678-A321F4D9A2C8 type=Device command_uuid=1ec2a267-1b32-4843-8ba0-2b06e80565c4 2021/05/30 12:46:40 level=debug service=nanomdm msg=no command retrieved id=E9085AF6-DCCB-5661-A678-BCE8F4D9A2C8 ``` -------------------------------- ### Enable Enrollment Migration Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Enable the HTTP endpoint for enrollment migrations. ```APIDOC ## Enable Enrollment Migration ### -migration * enable HTTP endpoint for enrollment migrations [NANOMDM_MIGRATION] NanoMDM supports a "lossy" form of MDM enrollment "migration." Essentially if a source MDM server can assemble enough of both Authenticate and TokenUpdate messages for an enrollment you can "migrate" enrollments by sending those Plist requests to the migration endpoint. Importantly this transfers the needed Push topic, token, and push magic to continue to send APNs push notifications to enrollments. This switch turns on the migration endpoint. ``` -------------------------------- ### Configuration Flags Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Various command-line flags to configure NanoMDM behavior. ```APIDOC ## Configuration Flags ### `-retro` * **Description**: Allows retroactive certificate-authorization association for enrollments that may lack it, potentially bypassing authorization checks for migrated devices. This flag enables the creation of a certificate association if none exists, but does not overwrite existing associations. * **Alias**: `NANOMDM_RETRO` ### `-version` * **Description**: Prints the current version of NanoMDM and exits. ### `-webhook-hmac-key string` * **Description**: Configures an HMAC HTTP header (`X-Hmac-Signature`) for webhook requests using the provided key. The header contains a Base-64 encoded SHA-256 HMAC digest of the request body. * **Alias**: `NANOMDM_WEBHOOK_HMAC_KEY` ### `-webhook-url string` * **Description**: Enables and specifies the URL for webhook callbacks. When MDM protocol events occur, NanoMDM sends an HTTP webhook request to this URL. The webhook is compatible with MicroMDM's webhook specification. * **Alias**: `NANOMDM_WEBHOOK_URL` ### `-auth-proxy-url string` * **Description**: Enables an authentication proxy and reverse proxies HTTP requests from the `/authproxy/` endpoint to the specified URL if the client provides device enrollment authentication. * **Alias**: `NANOMDM_AUTH_PROXY_URL` ### `-ua-zl-dc` * **Description**: Enables zero-length Digest Challenge mode for `UserAuthenticate` messages. Instead of responding with an HTTP 410 (declining management), NanoMDM responds with an empty Digest Challenge, allowing management of the user channel for that MDM user. This applies to 'directory' MDM users, not the 'primary' MDM user enrollment. * **Alias**: `NANOMDM_UA_ZL_DC` ``` -------------------------------- ### Manual Migration via POSTing Authenticate Message Source: https://context7.com/micromdm/nanomdm/llms.txt Perform a manual migration by sending an Authenticate message to the migration endpoint using a PUT request. Ensure the 'authenticate.plist' file contains the correct message. ```bash curl -u nanomdm:nanomdm -X PUT \ -H "Content-Type: application/xml" \ --data-binary @authenticate.plist \ 'http://127.0.0.1:9000/migration' ``` -------------------------------- ### Migration API Endpoint Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md The migration endpoint allows establishing an enrollment by sending raw `TokenUpdate` and `Authenticate` messages. It bypasses certificate validation and authentication, requiring only API HTTP authentication. ```bash # Example usage for migration endpoint (conceptual, actual command not provided in source) # curl -X POST -u nanomdm:nanomdm --data '{"message": "TokenUpdate or Authenticate payload"}' /migration ``` -------------------------------- ### Run ngrok for SCEP Proxy Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Use ngrok to create a public HTTPS tunnel to the local SCEP server running on port 8080. Note the generated public URLs, which will be used to access the SCEP service externally. Free ngrok accounts have a 2-hour time limit per tunnel. ```bash $ ./ngrok http 8080 ngrok by @inconshreveable (Ctrl+C to quit) Session Status online Session Expires 1 hour, 59 minutes Version 2.3.40 Region United States (us) Web Interface http://127.0.0.1:4040 Forwarding http://fd2a766cc645.ngrok.io -> http://localhost:8080 Forwarding https://fd2a766cc645.ngrok.io -> http://localhost:8080 [snip] ``` -------------------------------- ### Retrieve NanoMDM Server Version Source: https://context7.com/micromdm/nanomdm/llms.txt Fetch the current version of the running NanoMDM server. This endpoint does not require authentication. ```bash curl 'http://127.0.0.1:9000/version' ``` -------------------------------- ### POST /v1/push/{enrollment_id} Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Sends a push notification to a specific device to prompt it to check in with the MDM service. ```APIDOC ## POST /v1/push/{enrollment_id} ### Description Sends a push notification to a specific device to prompt it to check in with the MDM service. You can specify multiple enrollment IDs by comma-separating them. ### Method GET ### Endpoint /v1/push/{enrollment_id} ### Parameters #### Path Parameters - **enrollment_id** (string) - Required - The unique identifier of the device's enrollment. ### Request Example ```bash curl -u nanomdm:nanomdm 'http://127.0.0.1:9000/v1/push/99385AF6-44CB-5621-A678-A321F4D9A2C8' ``` ### Response #### Success Response (200) - **status** (object) - An object containing the results of the push notification attempt for each enrollment ID. - **[enrollment_id]** (object) - Details specific to the enrollment ID. - **push_result** (string) - A UUID indicating the success of the push notification. The absence of an error indicates success. #### Response Example ```json { "status": { "99385AF6-44CB-5621-A678-A321F4D9A2C8": { "push_result": "8B16D295-AB2C-EAB9-90FF-8615C0DFBB08" } } } ``` ``` -------------------------------- ### Migration Endpoint Source: https://context7.com/micromdm/nanomdm/llms.txt Facilitates the migration of MDM enrollments between storage backends or MDM servers. ```APIDOC ## PUT /migration ### Description Migrates MDM enrollments by sending raw Authenticate and TokenUpdate messages. This endpoint is typically used with tools like `nano2nano` or by manually POSTing plist data. ### Method PUT ### Endpoint `/migration` ### Parameters #### Request Body - **XML Plist** - Required - An Authenticate or TokenUpdate message in XML plist format. ### Request Example (Manual Migration) ```bash curl -u nanomdm:nanomdm -X PUT \ -H "Content-Type: application/xml" \ --data-binary @authenticate.plist \ 'http://127.0.0.1:9000/migration' ``` ### Notes - The migration endpoint needs to be enabled when starting the NanoMDM server using the `-migration` flag. - Tools like `nano2nano` can automate the migration process. ``` -------------------------------- ### Generate SecurityInfo Command with cmdr.py Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Use `cmdr.py` to generate a specific MDM command, such as `SecurityInfo`. This command is output as an XML plist. ```bash $ ./tools/cmdr.py SecurityInfo Command RequestType SecurityInfo CommandUUID d1b7fdda-52e1-45d1-80e6-8bf3b5d76f17 ``` -------------------------------- ### Enqueue MDM Commands Source: https://context7.com/micromdm/nanomdm/llms.txt Queues MDM commands for enrolled devices. Commands are in raw Apple plist format and are automatically pushed to devices. ```APIDOC ## POST /v1/enqueue/{enrollment_id} ### Description Enqueues an MDM command for a specific enrolled device. ### Method POST ### Endpoint `/v1/enqueue/{enrollment_id}` ### Parameters #### Path Parameters - **enrollment_id** (string) - Required - The unique identifier of the enrollment to send the command to. #### Query Parameters None #### Request Body - **(plist)** - Required - The MDM command in Apple plist format. ### Request Example ```bash curl -T - -u nanomdm:nanomdm \ 'http://127.0.0.1:9000/v1/enqueue/99385AF6-44CB-5621-A678-A321F4D9A2C8' << 'EOF' Command RequestType ProfileList CommandUUID fedd659e-fc3c-4e35-8bb1-c8f51ae542a5 EOF ``` ### Response #### Success Response (200) - **status** (object) - An object containing the push result for the enrollment. - **{enrollment_id}** (object) - Details about the push result. - **push_result** (string) - The result of the APNs push operation. - **command_uuid** (string) - The unique identifier of the enqueued command. - **request_type** (string) - The type of the MDM command. #### Response Example ```json { "status": { "99385AF6-44CB-5621-A678-A321F4D9A2C8": { "push_result": "16C80450-B79F-E23B-F99B-0810179F244E" } }, "command_uuid": "fedd659e-fc3c-4e35-8bb1-c8f51ae542a5", "request_type": "ProfileList" } ``` ``` -------------------------------- ### Generate and Enqueue MDM Command Source: https://github.com/micromdm/nanomdm/blob/main/docs/operations-guide.md Use the `cmdr.py` script to generate an MDM command Plist and then pipe it to `curl` to enqueue the command to one or more enrollments. The response includes the command UUID and request type. ```bash $ ./cmdr.py -r Command RequestType ProfileList CommandUUID d7408b5d-f314-461f-bc5e-4ff107c03857 ``` ```bash $ ./cmdr.py -r | curl -T - -u nanomdm:nanomm 'http://127.0.0.1:9000/v1/enqueue/E9085AF6-DCCB-5661-A678-BCE8F4D9A2C8' { "status": { "E9085AF6-DCCB-5661-A678-BCE8F4D9A2C8": { "push_result": "16C80450-B79F-E23B-F99B-0810179F244E" } }, "command_uuid": "1ec2a267-1b32-4843-8ba0-2b06e80565c4", "request_type": "ProfileList" } ``` ```bash $ ./cmdr.py -r | curl -T - -u nanomdm:nanomm 'http://127.0.0.1:9000/v1/enqueue/99385AF6-44CB-5621-A678-A321F4D9A2C8,E9085AF6-DCCB-5661-A678-BCE8F4D9A2C8' "status": { "99385AF6-44CB-5621-A678-A321F4D9A2C8": { "push_result": "4DE6E126-CC6C-37B2-7350-3AD1871C298F" }, "E9085AF6-DCCB-5661-A678-BCE8F4D9A2C8": { "push_result": "7B9D73CD-186B-CCF4-D585-AEE9E8E4F0F3" } }, "command_uuid": "9b7c63eb-14b4-4739-96b0-750a5c967371", "request_type": "ProvisioningProfileList" } ``` ```bash $ ./cmdr.py -r | curl -v -T - -u nanomdm:nanomdm '[::1]:9000/v1/enqueue/99385AF6-44CB-5621-A678-A321F4D9A2C8?nopush=1' { "no_push": true, "command_uuid": "598544b5-b681-4ce2-8914-ba7f45ff5c02", "request_type": "CertificateList" } ``` -------------------------------- ### Upload Push Certificate to NanoMDM Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md Concatenate the push certificate and its private key, then upload them to the NanoMDM API endpoint '/v1/pushcert' using curl. Authentication is done via Basic Auth with username 'nanomdm' and password 'nanomdm'. The private key must be unencrypted. ```bash cat /path/to/push.pem /path/to/push.key | curl -T - -u nanomdm:nanomdm 'http://127.0.0.1:9000/v1/pushcert' ``` ```text { "topic": "com.apple.mgmt.External.e3b8ceac-1f18-2c8e-8a63-dd17d99435d9" } ``` ```text 2021/05/30 12:26:18 level=info handler=log addr=127.0.0.1 method=PUT path=/v1/pushcert agent=curl/7.54.0 2021/05/30 12:26:18 level=info handler=store-cert msg=stored push cert topic=com.apple.mgmt.External.e3b8ceac-1f18-2c8e-8a63-dd17d99435d9 ``` -------------------------------- ### POST /mdm Source: https://github.com/micromdm/nanomdm/blob/main/docs/quickstart.md This endpoint is used by devices to enroll and check-in with the NanoMDM server. It handles authentication and token updates. ```APIDOC ## POST /mdm ### Description This endpoint is used by devices to enroll and check-in with the NanoMDM server. It handles authentication and token updates. ### Method PUT ### Endpoint /mdm ### Request Body This endpoint does not explicitly define a request body in the provided documentation, but it is expected to be part of the MDM protocol communication. ### Response #### Success Response (200) - **status** (object) - Indicates the status of the operation. - **[enrollment_id]** (object) - Details specific to the enrollment ID. - **push_result** (string) - A UUID indicating the success of a push notification. ### Response Example ```json { "status": { "99385AF6-44CB-5621-A678-A321F4D9A2C8": { "push_result": "8B16D295-AB2C-EAB9-90FF-8615C0DFBB08" } } } ``` ``` -------------------------------- ### MDM Enrollment Profile Configuration Source: https://context7.com/micromdm/nanomdm/llms.txt This XML configuration defines the MDM enrollment profile, including SCEP payload for certificate issuance and the MDM payload with server details and capabilities. ```xml PayloadContent PayloadContent Key Type RSA Challenge your-scep-challenge Key Usage 5 Keysize 2048 URL https://scep.example.org/scep PayloadIdentifier com.example.scep PayloadType com.apple.security.scep PayloadUUID CB90E976-AD44-4B69-8108-8095E6260978 PayloadVersion 1 AccessRights 8191 CheckOutWhenRemoved IdentityCertificateUUID CB90E976-AD44-4B69-8108-8095E6260978 PayloadIdentifier com.example.mdm PayloadType com.apple.mdm PayloadUUID 96B11019-B54C-49DC-9480-43525834DE7B PayloadVersion 1 ServerCapabilities com.apple.mdm.per-user-connections com.apple.mdm.bootstraptoken com.apple.mdm.token ServerURL https://mdm.example.org/mdm SignMessage Topic com.apple.mgmt.External.e3b8ceac-1f18-2c8e-8a63-dd17d99435d9 PayloadDisplayName MDM Enrollment PayloadIdentifier com.example.enrollment PayloadType Configuration PayloadUUID F9760DD4-F2D1-4F29-8D2C-48D52DD0A9B3 PayloadVersion 1 ```