# How Magisk Handles Module Upgrades and the Update Mechanism

> Discover how Magisk manages module upgrades by comparing version codes, downloading updates, and reinstalling modules. Learn about the Magisk update mechanism.

- Repository: [John Wu/Magisk](https://github.com/topjohnwu/Magisk)
- Tags: internals
- Published: 2026-03-05

---

**Magisk handles module upgrades by comparing `versionCode` values in `module.prop`, downloading updates via the `updateCheck` URL, and reinstalling through the `install_module` function while touching an `update` flag file to signal the Magisk app.**

The `topjohnwu/Magisk` repository implements a robust, file-based upgrade system for Magisk modules that ensures safe updates without breaking existing installations. This mechanism relies on specific metadata files, shell-based installation scripts, and flag files to coordinate between the core Magisk framework and the companion Android app.

## Understanding the Magisk Module Structure

Every Magisk module is a standard ZIP package containing a **`module.prop`** file at its root. This properties file defines the module's identity and upgrade behavior through several key fields:

- **`id`** – A unique identifier used as the directory name under `/data/adb/modules/`
- **`version`** – Human-readable version string
- **`versionCode`** – Integer used for deterministic version comparison
- **`updateCheck`** – Optional URL endpoint for fetching update metadata

When a module is installed, Magisk extracts this metadata to `/data/adb/modules/<id>/module.prop`, creating a persistent record that the upgrade mechanism references during version checks.

## The Magisk Module Upgrade Workflow

The upgrade process follows a deterministic sequence that ensures atomic replacement of module files while preserving the module's identity and state.

### Version Comparison and Detection

The Magisk app initiates upgrades by reading the installed **`/data/adb/modules/<id>/module.prop`**. It compares the local `versionCode` against the remote version available through the `updateCheck` URL or user-provided ZIP. If the remote `versionCode` is higher, the app marks the module as having an available upgrade.

### Fetching Updates via updateCheck

Modules that declare an **`updateCheck`** URL in their `module.prop` enable automatic update detection. The Magisk app contacts this endpoint to retrieve update metadata or the newer ZIP file directly, storing the download temporarily before triggering the installation process.

### The Re-installation Process

Magisk performs upgrades by re-running the **`install_module`** function defined in [`scripts/util_functions.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/util_functions.sh). Because the module's `id` remains unchanged, the installer:

1. Removes the existing directory at `/data/adb/modules/<id>`
2. Extracts and writes the new module files to the same location
3. Preserves module state files if necessary

This atomic replacement ensures no orphaned files remain from previous versions.

### Signaling Upgrade Completion with the Update Flag

After a successful reinstall, the installer creates an empty file named **`update`** inside the module directory to signal the Magisk app. The relevant code in [`scripts/util_functions.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/util_functions.sh) handles this:

```sh

# scripts/util_functions.sh – install_module()

if $BOOTMODE; then
    # Update info for Magisk app

    mktouch /data/adb/modules/$MODID/update
fi

```

This flag file at `/data/adb/modules/<id>/update` persists until the Magisk app reads it and updates its UI, typically displaying an "Updated" badge or refreshing the module list to reflect the new version.

## Manual Module Upgrades via CLI

Users can trigger upgrades manually without the Magisk app by using the command-line interface. The following command invokes the same `install_module` function used by the GUI:

```sh

# Download the newer module zip to device storage

# Then run the installer in boot mode

magisk --install-module /sdcard/NewMod.zip

```

This execution flow:
- Extracts `module.prop` to identify the module ID
- Removes the old installation at `/data/adb/modules/<id>`
- Copies new files and touches the `update` flag
- Cleans up temporary files upon completion

## Post-Upgrade Hooks and Cleanup

After the core upgrade completes, Magisk executes several hook scripts that allow modules to perform migration tasks or restart services:

- **[`customize.sh`](https://github.com/topjohnwu/Magisk/blob/main/customize.sh)** – Runs during installation to handle custom extraction logic or version-specific migrations
- **[`post-fs-data.sh`](https://github.com/topjohnwu/Magisk/blob/main/post-fs-data.sh)** – Executes after the kernel mounts filesystems but before Zygote starts, allowing modules to adjust permissions or prepare data directories
- **[`service.sh`](https://github.com/topjohnwu/Magisk/blob/main/service.sh)** – Runs late in the boot process when the system is fully operational, suitable for restarting daemons or applying runtime patches

The installer also cleans up stale state files such as `remove` or `disable` flags during the upgrade process, ensuring the module starts fresh with the new version while maintaining its enabled/disabled status as appropriate.

## Key Source Files Implementing Module Upgrades

The upgrade mechanism spans both native shell scripts and Java components within the Magisk codebase:

| File | Role |
|------|------|
| **[`scripts/util_functions.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/util_functions.sh)** – `install_module()` | Core installer function that handles both fresh installs and upgrades; creates the `update` flag file. |
| **[`app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java`](https://github.com/topjohnwu/Magisk/blob/main/app/shared/src/main/java/com/topjohnwu/magisk/StubApk.java)** | Provides `update(Context)` helper for app-side update coordination. |
| **[`app/stub/src/main/java/com/topjohnwu/magisk/DummyProvider.java`](https://github.com/topjohnwu/Magisk/blob/main/app/stub/src/main/java/com/topjohnwu/magisk/DummyProvider.java)** | Content provider stub that queries module state, including detection of the `update` flag file. |
| **[`docs/details.md`](https://github.com/topjohnwu/Magisk/blob/main/docs/details.md)** | Documents the upgrade flag behavior and UI expectations for module developers. |

## Summary

- Magisk modules are upgraded by reinstalling the ZIP package while preserving the module ID, ensuring atomic replacement of files.
- The **`install_module`** function in [`scripts/util_functions.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/util_functions.sh) handles both initial installations and upgrades, removing old files at `/data/adb/modules/<id>` before extracting new content.
- An empty **`update`** flag file is created at `/data/adb/modules/<id>/update` to signal the Magisk app that an upgrade occurred.
- Modules declare update endpoints via the **`updateCheck`** field in `module.prop`, enabling automatic version detection by comparing `versionCode` values.
- Post-upgrade hooks including **[`customize.sh`](https://github.com/topjohnwu/Magisk/blob/main/customize.sh)**, **[`post-fs-data.sh`](https://github.com/topjohnwu/Magisk/blob/main/post-fs-data.sh)**, and **[`service.sh`](https://github.com/topjohnwu/Magisk/blob/main/service.sh)** allow modules to execute migration logic and restart services.

## Frequently Asked Questions

### How does Magisk detect available module updates?

The Magisk app reads the installed `module.prop` from `/data/adb/modules/<id>/module.prop` and compares the local `versionCode` against the remote version fetched from the module's declared `updateCheck` URL. If the remote `versionCode` is higher, the app marks the module as having an update available.

### What happens to old module files during an upgrade?

During an upgrade, the `install_module` function in [`scripts/util_functions.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/util_functions.sh) completely removes the existing directory at `/data/adb/modules/<id>` before extracting the new module files. This ensures no stale files remain from previous versions while preserving the module's identity through its consistent ID.

### Can I upgrade Magisk modules without using the official app?

Yes, you can trigger manual upgrades via the command line using `magisk --install-module /path/to/NewMod.zip`. This command invokes the same `install_module` function used by the GUI, performing the version comparison, atomic replacement, and creation of the `update` flag file without requiring the Magisk app interface.

### What is the purpose of the update flag file in Magisk modules?

The empty file located at `/data/adb/modules/<id>/update` serves as a persistent signal to the Magisk app that the module has just been upgraded. The app scans for this flag during startup to display "Updated" badges in the UI and trigger any necessary post-install hooks defined in the module's scripts.