With Microsoft sunsetting App Center and CodePush, many in the React Native community are seeking alternatives for over-the-air (OTA) updates.
In order to let developers keep using CodePush functionality after App Center is fully retired, Microsoft created a standalone version of CodePush Server that can be deployed and used independently from App Center itself.
This guide will show you how to deploy and configure your own CodePush Server in a self-hosted environment and CodePush Command Line Interface.
This guide assumes you have a React Native app that is currently using CodePush from App Center and that you are comfortable using the command line interface (CLI) to release OTA updates, should have basic understanding of Azure App Service, Azure Blob Storage and Azure Resource Manager.
To deploy CodePush to Azure, an active Azure account and subscription are needed. During the deployment process script will create Azure services needed to run CodePush Server including:
For user authentication and to register your React Native application on self-managed server, a GitHub or Microsoft OAuth application is needed (we will use GitHub OAuth application in this example. Please follow official documentation to create one).
$ az --version
azure-cli 2.67.0
core 2.67.0
telemetry 1.1.0
Dependencies:
msal 1.31.0
azure-mgmt-resource 23.1.1
Python location '/opt/homebrew/Cellar/azure-cli/2.67.0_1/libexec/bin/python'
Extensions directory '/Users/username/.azure/cliextensions'
Python (Darwin) 3.12.8 (main, Dec 3 2024, 18:42:41) [Clang 16.0.0 (clang-1600.0.26.4)]
Legal docs and information: aka.ms/AzureCliLegal
Your CLI is up-to-date.$ az loginand follow the instructions in the browser.
$ az account set --subscription$ az group create --name --locationHelp tip: you can find the list of available locations by running
$ az account list-locations --output tableWe recommend you to select the location that is the closest to your target audience to provide the best performance and throughput to your users.
Upon successful creation, you will see output similar to the following:
{
"id": "/subscriptions/2979d791-c9cc-4cb4-9c25-7ccf2473e983/resourceGroups/codepushselfhosted",
"location": "eastus",
"managedBy": null,
"name": "codepushselfhosted",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}To be able to do that checkout the CodePush Server repository:
$ git clone https://github.com/microsoft/code-push-server.gitand navigate to the api directory.
$ az deployment group create --resource-group --template-file ./codepush-infrastructure.bicep --parameters project_suffix=
az_location= github_client_id= github_client_secret= microsoft_client_id= microsoft_client_secret=OAuth parameters (both GitHub and Microsoft) are optional. It is possible to specify them after the deployment in environment settings of Azure WebApp.
Upon successful deployment, you will see output similar to the following:
Resource and property changes are indicated with these symbols:
+ Create
* Ignore
The deployment will update the following scope:
Scope: /subscriptions/2979d791-c9cc-4cb4-9c25-7ccf2473e983/resourceGroups/ccp_group_name
+ Microsoft.Storage/storageAccounts/codepushstoragetst [2022-09-01]
apiVersion: "2022-09-01"
id: "/subscriptions/2979d791-c9cc-4cb4-9c25-7ccf2473e983/resourceGroups/ccp_group_name/providers/Microsoft.Storage/storageAccounts/codepushstoragetst"
kind: "StorageV2"
location: "westeurope"
name: "codepushstoragetst"
properties.allowBlobPublicAccess: true
properties.minimumTlsVersion: "TLS1_2"
properties.publicNetworkAccess: "Enabled"
sku.name: "Standard_LRS"
type: "Microsoft.Storage/storageAccounts"
+ Microsoft.Web/serverfarms/codepush-asp-tst [2022-03-01]
apiVersion: "2022-03-01"
id: "/subscriptions/2979d791-c9cc-4cb4-9c25-7ccf2473e983/resourceGroups/ccp_group_name/providers/Microsoft.Web/serverfarms/codepush-asp-tst"
location: "westeurope"
name: "codepush-asp-tst"
properties.reserved: true
sku.name: "S1"
type: "Microsoft.Web/serverfarms"
+ Microsoft.Web/sites/codepush-tst [2022-03-01]
apiVersion: "2022-03-01"
id: "/subscriptions/2979d791-c9cc-4cb4-9c25-7ccf2473e983/resourceGroups/ccp_group_name/providers/Microsoft.Web/sites/codepush-tst"
location: "westeurope"
name: "codepush-tst"
properties.httpsOnly: true
properties.serverFarmId: "/subscriptions/2979d791-c9cc-4cb4-9c25-7ccf2473e983/resourceGroups/ccp_group_name/providers/Microsoft.Web/serverfarms/codepush-asp-tst"
properties.siteConfig: "*******"
type: "Microsoft.Web/sites"
+ Microsoft.Web/sites/codepush-tst/basicPublishingCredentialsPolicies/scm [2022-03-01]
apiVersion: "2022-03-01"
id: "/subscriptions/2979d791-c9cc-4cb4-9c25-7ccf2473e983/resourceGroups/ccp_group_name/providers/Microsoft.Web/sites/codepush-tst/basicPublishingCredentialsPolicies/scm"
name: "scm"
properties.allow: true
type: "Microsoft.Web/sites/basicPublishingCredentialsPolicies"From api directory run the following command:
$ az webapp up --sku --nameBe patient, it may take a few minutes to build and deploy the app. In the backgroud Azure will crete AppServicePlan, update App settings, Creating zip with contents of directory, build the app and deploy it to the Azure WebApp.
Upon successful deployment, you will see output similar to the following:
Creating AppServicePlan 'codepush-asp-ccp' or Updating if already exists
Readonly attribute name will be ignored in class <class 'azure.mgmt.web.v2023_01_01.models._models_py3.AppServicePlan'>
Creating zip with contents of dir /Users/username/code-push-server/api ...
Getting scm site credentials for zip deployment
Starting zip deployment. This operation can take a while to complete ...
Deployment endpoint responded with status code 202
Polling the status of async deployment. Start Time: 2024-12-18 10:29:03.070207+00:00 UTC
Status: Building the app... Time: 0(s)
Status: Building the app... Time: 17(s)
Status: Building the app... Time: 33(s)
Status: Building the app... Time: 49(s)
Status: Building the app... Time: 66(s)
Status: Building the app... Time: 82(s)
Status: Building the app... Time: 98(s)
Status: Building the app... Time: 115(s)
Status: Building the app... Time: 132(s)
Status: Building the app... Time: 148(s)
Status: Building the app... Time: 164(s)
Status: Building the app... Time: 180(s)
Status: Building the app... Time: 197(s)
Status: Building the app... Time: 214(s)
Status: Building the app... Time: 230(s)
Status: Building the app... Time: 246(s)
Status: Building the app... Time: 262(s)
Status: Building the app... Time: 279(s)
Status: Building the app... Time: 296(s)
Status: Building the app... Time: 312(s)
Status: Building the app... Time: 328(s)
Status: Building the app... Time: 344(s)
Status: Building the app... Time: 363(s)
Status: Build successful. Time: 380(s)
Status: Site started successfully. Time: 395(s)
You can launch the app at http://<app name from previous step>.azurewebsites.netCongratulations! You have successfully deployed CodePush Server to Azure and you may
open https://<your app name>.azurewebsites.net that will show you welcome message
Welcome to the CodePush REST API!Revopush provides consulting services to install and configure a standalone CodePush Server in your cloud environment. This includes infrastructure provisioning, server setup, and integration with existing systems.
To run command of CodePush management CLI you need to have Node.js and npm installed on your machine. At the moment of writing this guide, we used Node.js v18.20.4 and npm v10.9.1 to build and install CodePush management CLI.
For more information on installing Node.js and npm, please visit the official website.
$ git clone https://github.com/microsoft/code-push-server.gitand navigate to the cli directory.
$ npm install$ npm run build$ npm install -g code-push-standalone$ code-push-standalone -hUpon successful deployment, you will see output similar to the following:
_____ __ ___ __
/ ___/__ ___/ /__ / _ \__ _____ / /
/ /__/ _ \/ _ / -_) ___/ // (_-</ _ \
\___/\___/\_,_/\__/_/ \_,_/___/_//_/ CLI v0.0.1
======================================
CodePush is a service that enables you to deploy mobile app updates directly to your users' devices.
Usage: code-push-standalone <command>
Commands:
code-push-standalone access-key View and manage the access keys associated with your account
code-push-standalone app View and manage your CodePush apps
code-push-standalone collaborator View and manage app collaborators
code-push-standalone debug View the CodePush debug logs for a running app
code-push-standalone deployment View and manage your app deployments
code-push-standalone link Link an additional authentication provider (e.g. GitHub) to an existing CodePush account
code-push-standalone login Authenticate with the CodePush server in order to begin managing your apps
code-push-standalone logout Log out of the current session
code-push-standalone patch Update the metadata for an existing release
code-push-standalone promote Promote the latest release from one app deployment to another
code-push-standalone register Register a new CodePush account
code-push-standalone release Release an update to an app deployment
code-push-standalone release-react Release a React Native update to an app deployment
code-push-standalone rollback Rollback the latest release for an app deployment
code-push-standalone session View and manage the current login sessions associated with your account
code-push-standalone whoami Display the account info for the current login session
Options:
--help Show help [boolean]
-v, --version Show version number [boolean]$ code-push-standalone registerand navigate to the cli directory.
A browser is being launched to authenticate your account. Follow the instructions it displays to complete your login.
Enter your access key: yQKR17duPW0h9zzfQI_sSI896t4LVJMn2aoEZlThis key will be persisted in the .code-push.config file in user's home folder. To terminate current session run code-push-standalone logout command.
$ code-push-standalone app addWe suggest you to create separate application for each platform (iOS, Android) with CodePush server. This way, you can manage and release updates to them separately. Example
code-push-standalone app add MyApp-Android
code-push-standalone app add MyApp-iOSUpon successful creation, you will see output similar to the following:
Successfully added the "MyApp-Android" app, along with the following default deployments:
┌────────────┬────────────────────────────────────────┐
│ Name │ Deployment Key │
├────────────┼────────────────────────────────────────┤
│ Production │ iTPp_VDEFilxBSRQElJz5Jnv7IhgVJMn2aoEZl │
├────────────┼────────────────────────────────────────┤
│ Staging │ ol3aTQxSTRaLjI3MZszdw_B20i_8VJMn2aoEZl │
└────────────┴────────────────────────────────────────┘
Successfully added the "MyApp-iOS" app, along with the following default deployments:
┌────────────┬────────────────────────────────────────┐
│ Name │ Deployment Key │
├────────────┼────────────────────────────────────────┤
│ Production │ OECdNPjYzjs_1el1QlvClu3nRVfdVJMn2aoEZl │
├────────────┼────────────────────────────────────────┤
│ Staging │ nUtMITaUV-ne_GJWcnngnO6htnpzVJMn2aoEZl │
└────────────┴────────────────────────────────────────┘At this point, you have successfully registered your account and created an app on your CodePush Server.
You need to update your React Native app to query for updates against your new CodePush Server. Due to React Native nature this change will require you to release new version of the app for AppStore and PlayStore.
<key>CodePushDeploymentKey</key>
<string>deployment-key</string>
<key>CodePushServerURL</key>
<string>server-url</string><string moduleConfig="true" name="CodePushDeploymentKey">deployment-key</string>
<string moduleConfig="true" name="CodePushServerUrl">server-url</string>Once your app has been configured to query for updates against the CodePush server, you can begin releasing updates to it.
$ code-push-standalone release-react MyApp-iOS ios --outputDir ./CodePush --targetBinaryVersion 0.0.1This command will create a new release for the MyApp-iOS app, targeting the ios platform, and output the generated bundle to the ./CodePush directory. Upon successful release, you will see output similar to the following:
Running "react-native bundle" command:
node node_modules/react-native/cli.js bundle --assets-dest ./CodePush --bundle-output CodePush/main.jsbundle --dev false --entry-file index.js --platform ios
Welcome to Metro v0.81.0
Fast - Scalable - Integrated
info Writing bundle output to: CodePush/main.jsbundle
info Done writing bundle output
info Copying 1 asset files
info Done copying assets
private key was not provided
Releasing update contents to CodePush:
Upload progress:[==================================================] 100% 0.0s
Successfully released an update containing the "./CodePush" directory to the "Staging" deployment of the "MyApp-iOS" app.Under the hood, the code-push-standalone release-react command will bundle your app's JavaScript code and assets, upload them to the CodePush server, and create a new release for the specified deployment.
The full list of options for fine-grained tuning of the release process can be found by running:
$ code-push-standalone release-react --help$ code-push-standalone deployment history MyApp-iOS StagingUpon successful execution, you will see output similar to the following:
┌───────┬────────────────┬─────────────┬───────────┬─────────────────┬──────────────────────┐
│ Label │ Release Time │ App Version │ Mandatory │ Description │ Install Metrics │
├───────┼────────────────┼─────────────┼───────────┼─────────────────┼──────────────────────┤
│ v1 │ 27 minutes ago │ 0.0.1 │ No │ │ No installs recorded │
├───────┼────────────────┼─────────────┼───────────┼─────────────────┼──────────────────────┤
│ v2 │ 4 minutes ago │ 0.0.1 │ No │ fix misspelling │ No installs recorded │
└───────┴────────────────┴─────────────┴───────────┴─────────────────┴──────────────────────┘When deciding between a Standalone CodePush Server and a Software as a Service (SaaS) solution, it's important to consider various factors such as overall cost, scalability, and maintenance. Based on what we have observed at Revopush, for production-grade applications, you will need at least:
We will use the following numbers for an example:
It gives us: 200 000 users X 5 Mb X 5 bundles/month = 5 000 000 MB = ~4 882 GB = ~4.76 TB
Azure gives you 100 GB of free bandwidth per month. What is on top is charged $0.087 per GB what for given example will cost 416$ per month.
Alternatively, you can try Revopush OTA and enjoy all the benefits without the hassle or review CodePush alternatives