Self-hosted React Native OTA updates (push + pull)
npm install rn-otarn-ota lets you push JavaScript bundles to your own server and pull updates inside the app, without relying on thirdβparty services.
react-native-restart support
sh
npm install rn-ota
`
$3
`sh
npm install react-native-restart
`
---
ποΈ Project Structure
`
project-root
βββ ota.config.json
βββ ota/
β βββ index.android.bundle
β βββ index.ios.bundle
β βββ manifest.json
`
---
βοΈ Configuration
Create ota.config.json in your project root:
`json
{
"version": "1.0.1",
"binaryVersion": "1.0.0",
"server": {
"host": "your-server.com",
"user": "username",
"password": "password",
"path": "/public/ota"
}
}
`
---
π Push OTA Update (CLI)
`sh
npx rn-ota push android
npx rn-ota push ios
`
This will:
* Bundle JS
* Generate SHA256 hash
* Create manifest.json
* Upload bundle + manifest to your server
---
π Manifest Format
`json
{
"version": "1.0.1",
"binaryVersion": "1.0.0",
"platform": "android",
"bundle": "index.android.bundle",
"hash": ""
}
`
---
π² Pull OTA Update (JS)
`js
import { pullUpdate, restartApp } from "rn-ota";
const result = await pullUpdate(
"https://your-server.com/ota",
"1.0.0", // current JS version
"1.0.0" // native app version
);
if (result.updated) {
restartApp();
}
`
---
π Restart Logic
$3
* Uses native Activity restart (safe & reliable)
* Reloads OTA bundle immediately
$3
* App cannot be restarted programmatically
* Update applies on next cold launch
---
π§ Android Native Setup (REQUIRED)
$3
MainApplication.java
`java
@Override
protected String getJSBundleFile() {
File file = new File(
getApplicationContext().getFilesDir(),
"index.android.bundle"
);
return file.exists()
? file.getAbsolutePath()
: super.getJSBundleFile();
}
`
---
$3
`java
packages.add(new RNOtaRestartPackage());
`
---
π Security
* SHA256 bundle verification
* Corrupt bundles rejected
* Fallback to embedded bundle
---
β What rn-ota does NOT do
* β Modify native code
* β Bypass App Store policies
* β Force iOS restart
* β Delta updates (yet)
---
π§ Best Practices
* Change version on every OTA push
* Match binaryVersion with app build
* Restart app after update
* Always keep a fallback bundle
---
π§ͺ Debugging
`js
console.log("OTA VERSION", result.version);
``