### 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
```