Introduction
OpenMDM is an embeddable Mobile Device Management SDK you drop into your existing TypeScript application.
Introduction
OpenMDM is a Mobile Device Management (MDM) library you embed in your own backend, not a separate server you deploy and integrate with. You add a few packages, point the SDK at your existing database, mount a Hono router at /mdm, and your app can now enroll, command, and monitor Android devices.
This is pre-1.0 software. The core APIs work and the packages are published to npm, but minor versions may still break the wire protocol before 1.0. Pin exact versions in production.
Who this is for
- You have an existing Node.js / TypeScript backend (Hono today; Express/Fastify/Next.js adapters are on the roadmap).
- You need to manage fleet-scale Android devices — kiosk terminals, logistics handhelds, retail POS, field service tablets — and you want that data in the same database your app already uses.
- You do not want to run a separate MDM server, integrate with its API, and reconcile two user models.
If that describes you, OpenMDM is the shortest path from "our app needs device management" to "our app has device management, deployed next to the existing app code."
Who this is NOT for
- Consumer BYOD scenarios. OpenMDM targets company-owned devices in Device Owner mode. It can do Profile Owner too, but the docs and examples here focus on the Device Owner path.
- iOS. OpenMDM is Android-only. Apple's MDM protocol is a different animal and is not on the roadmap.
- Regulated zero-trust environments that demand a hardware-rooted identity today. Hardware-rooted enrollment (Keystore-attested) lands in Phase 2b; until then, enrollment is HMAC-signed but not hardware-attested.
What the packages actually do
OpenMDM is a monorepo of small packages. You compose the ones you need:
| Package | What it is |
|---|---|
@openmdm/core | The SDK itself: device/policy/command managers, event bus, enrollment, webhook delivery. Framework- and database-agnostic — it takes adapters for everything it touches. |
@openmdm/drizzle-adapter | DatabaseAdapter implementation over Drizzle ORM. Supports Postgres, MySQL, and SQLite via the standard Drizzle dialects. |
@openmdm/hono | HTTP routes. Mounts all /agent/* and admin endpoints onto any Hono app. Runs on Node, Bun, Deno, Workers, Vercel. |
@openmdm/push-fcm | Firebase Cloud Messaging push adapter. Real Firebase Admin SDK, data-only messages, token invalidation. |
@openmdm/push-mqtt | MQTT push adapter for air-gapped or private fleets without Google Play Services. |
@openmdm/storage-s3 | Presigned URL issuer for APK uploads. Works with AWS S3, MinIO, DigitalOcean Spaces. |
@openmdm/plugin-kiosk | Kiosk mode lifecycle: enter/exit, lockout on exit-password failures. |
@openmdm/plugin-geofence | Circular + polygon zones with dwell time and scheduling. |
@openmdm/client | Device-side SDK consumed by the Android agent. You usually don't touch this unless you're building a custom agent. |
@openmdm/cli | Admin CLI: openmdm device list, openmdm policy apply, openmdm stats. Talks to your real MDM instance via a config file. |
The minimum viable setup is core + drizzle-adapter + hono + one push provider. Everything else is additive.
How it fits into your app
OpenMDM does not own a process. It is a library your server already imports:
┌────────────────── Your backend (Hono, Node) ───────────────────┐
│ │
│ Your routes OpenMDM routes Your jobs │
│ /api/* /mdm/* (mounted) cron, queues │
│ │ │ │ │
│ └─────────────┬───────┴─────┬─────────────┘ │
│ ▼ ▼ │
│ createMDM({ database, push, plugins }) │
│ │ │ │
│ ▼ ▼ │
│ Your Postgres FCM / MQTT │
│ │
└────────────────────────────────────────────────────────────────┘
▲
│ HTTPS + FCM
▼
┌─────────────┐
│ Android │ (openmdm-android agent,
│ device │ separate repo)
└─────────────┘A single createMDM() call returns an MDMInstance with managers (devices, policies, commands, apps, groups) and an event bus. Your own code calls those managers directly — same process, same transaction boundary, same database.
Where to go next
- Installation — the real packages, the real config shape.
- Quick Start — end-to-end working example against Hono + Postgres + FCM.
- Architecture — the control flow for enrollment, heartbeats, and commands. Read this before making architectural decisions.
- Commands vs Policies — the single most confusing distinction for newcomers. Read before writing any policy.
- Agent Wire Protocol — why
/agent/*responses use an envelope and how v1/v2 coexist during rollout.