Skip to content
MDMesh-appPublic

About

A modern, self-hosted Android MDM — fleet control, kiosk, app delivery, and signed auto-updates, with a console that doesn't feel like 2012.

Topics

Resources

Contributing

Security policy

Stars

30 stars

Watchers

3 watching

Forks

Latest commit

 

History

341 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

◧ MDMesh

A modern, self-hosted Android MDM — fleet control, kiosk, app delivery, and signed auto-updates, with a console that doesn't feel like 2012.

Release License PRs welcome Server Console Agent Deploy

Quick start · Features · Full setup · Architecture · Contributing · Roadmap


MDMesh console — fleet overview

The MDMesh console — overview (shown with sample data).


What is MDMesh?

MDMesh is an open-source Mobile Device Management platform for Android: enroll devices as Device Owner via a QR code, then manage them from a clean web console — push apps, lock devices into kiosk mode, track location, run remote actions, and keep the whole fleet (server and agent) updated with signed, auto-rolling-back releases.

It began as a fork of Headwind MDM and is being rebuilt into a distinct product across four planes:

Plane What it is Stack
Control plane The MDM server / REST API Java · Jersey · Guice · MyBatis · PostgreSQL
Admin console The modern web UI in this README React · TypeScript · Vite
Device agent A from-scratch Device-Owner app Kotlin · coroutines · WorkManager
Edge + updates TLS edge, tunnel, signed updater/recovery Caddy · Cloudflare Tunnel · minisign

Our goal

A genuinely complete, robust, and modernized open-source MDM — not a museum piece with a paywalled "enterprise edition." Kiosk, app delivery, location, reliable connectivity, one-command deployment, and a real CI/CD auto-update pipeline are all in the open-source core. The agent is engineered against a versioned, capability-negotiated protocol so the Android version treadmill stays cheap to maintain, and old agents keep working across server updates.


✨ Features

🛰 Fleet management Groups, configurations, live status, and a fast device list with search + filters.

🔒 Kiosk / COSU Single-app or multi-app lock-task with a custom home launcher and a crash-loop guard.

📦 App delivery A library + custom-APK upload + F-Droid, silent install/upgrade, and a deploy flow.

📍 Location Passive or active tracking, history trail, and a Leaflet map on the device page.

🔌 Reliable connectivity Instant wake channel when charging, battery-aware otherwise; survives reboots + self-updates.

♻️ Signed auto-update One-click or unattended server updates with DB backup + auto-rollback on quick-start installs, plus a recovery page.

Full feature list
  • Enrollment — QR-code Device-Owner provisioning (factory-reset → scan); one signed APK serves every deployment (server URL delivered in the QR, not baked in).
  • Modern console — dashboard, fleet views, device detail, app catalog, enrollment, settings; dark/light themes; keyboard-friendly and responsive.
  • Remote actions — lock-screen message, alert, ring, lock, reboot, passcode reset, factory wipe, connectivity power mode, location mode — all capability-gated so old agents never get a command they can't run.
  • Kiosk — COSU lock-task, home-screen replacement, allowed apps (per-app "Show in kiosk"), themed app grid, crash-loop protection.
  • App management — upload/parse APKs, F-Droid catalog, silent Device-Owner install/upgrade from your server or any HTTPS host, version & downgrade gating, and Library removal that leaves installed apps alone.
  • Telemetry — battery, storage, network, Android version, Device-Owner status, lifecycle event timeline.
  • Deployment — one ./setup.sh: Docker Compose with bundled auto-HTTPS (Caddy) for your own domain, or a permanent Cloudflare Tunnel; a native (non-Docker) installer; generated secrets.
  • CI/CD auto-update — tag a release → CI builds & signs artifacts (Ed25519/minisign) + a manifest → every deployment notices and verifies it. Quick-start (registry-image) installs then update server/web (on approval, or unattended) with a database backup and automatic rollback on failure; from-source Docker and native installs show the update and the command to apply it. A decoupled recovery service stays up if an update breaks the main server.
  • Staged device rollout — push the newest compatible agent APK to a hand-picked canary set, watch it land, then promote to the fleet — mirrored from your own origin, integrity-checked.
  • Backward compatibility — versioned /agent/v1 contract (additive-only, golden contract test in CI), so a newer server keeps serving older agents.
  • Desired-state configuration — saving a configuration makes its devices converge to it: the server hashes the configuration into a revision and pushes one config.apply command whenever a device's applied revision differs, at the next check-in. The device detail page shows sync state and per-field outcomes; the configuration list shows how many of its devices are in sync. Only capability-advertising agents receive it — older agents show "agent too old" instead of silently ignoring it. Enforced fields (19): main app, kiosk mode + exit/home/recents/notifications/system-info/keyguard/lock-buttons, kiosk exit password, background/text color, icon size, Wi-Fi, Bluetooth, USB storage, block screenshots, block factory reset, and location reporting mode. The kiosk allows the configuration's installed apps that have "Show in kiosk" on. Name and description are configuration metadata and are not sent to devices.

📸 The console

Device list
Devices — fleet at a glance with status, configuration, and an update banner.



Device detail
Device detail — live status, location, hardware, and the remote-action console.



App catalog
Apps — library, custom APKs, and F-Droid, with one-click deploy.



Staged agent rollout
Staged canary → fleet agent-APK rollout, with live progress.

Screenshots show the real console rendered with representative sample data. Regenerate them with cd web && npm run build && cd ../scripts/shots && npm install && npx playwright install chromium && node capture.mjs (see CONTRIBUTING.md).


🚀 Quick start

Requirements: Docker + Docker Compose v2 + openssl/curl. A Linux host.

Option A — one line, no clone (published images)

bash <(curl -fsSL https://raw.githubusercontent.com/MDMesh-app/MDMesh/main/quickstart.sh)

Pulls the released images from GHCR (no build), generates secrets, brings the stack up in ./mdmesh, and prints the console URL + a temporary admin password. (Needs a published release with public GHCR packages — or docker login ghcr.io first; see RELEASING.md.) Image tags carry no v prefix: release v0.3.2 publishes ghcr.io/mdmesh-app/mdmesh-server:0.3.2 (and :latest).

Option B — from source (clone + build)

git clone https://github.com/MDMesh-app/MDMesh.git
cd MDMesh
./setup.sh           # interactive: Cloudflare Tunnel, or your own HTTPS domain

Either way, setup.sh/quickstart.sh is interactive (Cloudflare Tunnel or your own HTTPS domain), generates your secrets, and prints the console URL + a generated admin password. Then:

  1. Open the console — you'll be prompted to set your own password on first login.
  2. Go to Enroll and generate a QR code.
  3. Factory-reset an Android device and tap the welcome screen 6× to open the QR scanner (or use adb shell dpm set-device-owner for a dev device).
  4. Scan the QR — the device enrolls as Device Owner and checks in.

No Docker? Run sudo ./setup.sh --native on Debian 12/13 or Ubuntu 24.04; it needs Node ≥ 20.19 and a JDK 17 first where the distro doesn't ship them (see DEPLOY.md). Full details, hosting modes, updates, recovery, and uninstalling are in the full setup guide → DEPLOY.md.


🧭 Where to go next

I want to… Read
Deploy it properly (domains, tunnels, updates, recovery) DEPLOY.md
Understand the codebase layout (the four planes) STRUCTURE.md + docs/adr
Contribute code, file a bug, or request a feature CONTRIBUTING.md
Cut and sign a release RELEASING.md
Understand the agent internals docs/agent-architecture.md

🗺 Roadmap

  • ✅ Modern React + TypeScript console
  • ✅ From-scratch Kotlin Device-Owner agent (versioned, capability-negotiated protocol)
  • ✅ Kiosk / COSU + custom launcher
  • ✅ App catalog + silent deploy
  • ✅ Location tracking + history + map
  • ✅ Reliable always-on connectivity (wake channel, reboot/self-update resume)
  • ✅ One-command deployment (Docker + Caddy auto-HTTPS + Cloudflare Tunnel + native installer)
  • ✅ CI/CD: signed releases, one-click/unattended server update + auto-rollback + recovery page
  • ✅ Staged canary → fleet agent-APK rollout
  • 🔜 Live remote control (screen view + input, WebRTC + self-hosted TURN)
  • 🔭 OEM-privileged tier (Knox / Zebra adapters) — parked behind the capability layer

🤝 Contributing

Contributions are welcome — code, docs, bug reports, and ideas. Start with CONTRIBUTING.md for the dev setup (server, agent, console), build/test commands, and conventions.

  • 🐞 Found a bug? Open a bug report.
  • 💡 Have an idea? Open a feature request.
  • 🔧 Sending a PR? The PR template has the checklist — small, focused PRs with tests + docs are easiest to merge.

One hard rule for the agent ↔ server contract: the /agent/v1 API is additive-only so older agents keep working. See ADR-0009.


📜 License & credits

MDMesh is licensed under the Apache License 2.0.

It is a fork of and builds on Headwind MDM by Headwind Solutions LLC, also Apache-2.0. The licensing and rebrand rationale is recorded in ADR-0008. Trademarks and brand names belong to their owners.

About

A modern, self-hosted Android MDM — fleet control, kiosk, app delivery, and signed auto-updates, with a console that doesn't feel like 2012.

Topics

Resources

Contributing

Security policy

Stars

30 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages