A self-hosted Over-The-Air (OTA) updates server for Expo/RN applications that gives you complete control over your app's update distribution. Built with Next.js and TypeScript, it implements the expo-updates protocol while providing additional features for enterprise use.
- Xavia OTA Updates Server
This system provides a robust OTA update infrastructure with these key components:
- Updates Server: A Next.js application handling OTA update distribution.
- Admin Dashboard: Web interface for update management.
- Blob Storage: Flexible and extensible blob storage support.
- Database Layer: Supports PostgreSQL for tracking (no sensitive or personal data is collected) and insights.
-
β¨ Full compatibility with
expo-updates
protocol - Seamlessly integrates with Expo applications using the standard update protocol. -
π Runtime version management and rollback support - Manage different app versions and quickly rollback to previous versions if issues arise.
-
π³ Docker support for easy deployment - Get up and running quickly with containerized deployment using Docker and Docker Compose.
-
ποΈ Multiple blob storage backends: Abstracted blob storage interface that allows you to plug in your own storage solutions. Implement the simple interface to integrate with any storage backend of your choice.
-
π Release history tracking - Keep track of all your releases with detailed metadata including timestamps, commit hashes and commit messages.
-
π Insights - Get insights into your update distribution with detailed analytics.
The easiest way to deploy Xavia OTA is using our public Docker image. The image is available on Docker Hub at xaviaio/xavia-ota.
-
You can copy the
docker-compose.yml
file in thecontainers/prod
folder and set the environment variables properly. -
Or if you like the longer route, you can pull the image and run it manually
docker run -d -p 3000:3000 xaviaio/xavia-ota -e HOST=http://localhost:3000 ...
Check this on how to run load testing for your OTA server in your deployment infrastructure.
-
Clone the repository and install dependencies:
git clone [email protected]:xavia-io/xavia-ota.git cd xavia-ota npm install
-
Copy the example local env file:
cp .env.example.local .env.local
-
Configure your environment variables in
.env.local
. The minimal required configuration is:HOST=http://localhost:3000 BLOB_STORAGE_TYPE=local DB_TYPE=postgres ADMIN_PASSWORD=your-admin-password PRIVATE_KEY_BASE_64=your-base64-encoded-private-key POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres POSTGRES_DB=releases_db POSTGRES_HOST=localhost POSTGRES_PORT=5432
-
Start the development server:
npm run dev
The server and admin dashboard will be available at http://localhost:3000
.
Refer to Storage & Database Configuration for more configuration options.
The code signing is done using a private key. The private key is used to sign the updates. The client uses a certificate to verify the signature of the update.
To read more about code signing for your app and how you can generate the secrets, please refer to the expo code signing documentation.
To use the OTA updates in your React Native app, please refer to the expo-updates configuration.
We provide a simple script build-and-publish-app-release.sh
in the scripts
folder to build and publish your app updates, copy it to your RN app root folder and run it from there:
./build-and-publish-app-release.sh <runtimeVersion> <your-xavia-ota-url>
Important: Make sure the runtime version is the same as the one you use in your expo-updates config in your app. Refer to the React Native app configuration for more information.
Example:
./build-and-publish-app-release.sh 1.0.0 http://localhost:3000
This script will:
- Build your app using
expo export
- Package the update with metadata
- Upload it to your Xavia OTA server
The script will show you the commit hash and message for confirmation before uploading.
Note: Make sure the script is executable (
chmod +x scripts/build-and-publish-app-release.sh
)
We use a simple rollback-forward mechanism. When a new update is published, it becomes the "active" update and the previous update, let's call it "inactive" update, is still available in your server but not served to the clients.
If anything goes wrong with the active update, and you want to rollback to the inactive one, you can simply click a button in the admin dashboard.
What happens behind the scenes is that we copy the inactive update with a new timestamp and push it to the front of the queue of updates, effectively making it the new active update.
For more information about the admin dashboard, please refer to the Admin Dashboard documentation.
- Framework: Next.js 15+
- Language: TypeScript
- Database: PostgreSQL 14
- UI Library: Chakra UI (v2) and Tailwind CSS for styling
- Container: Docker & Docker Compose
- Local filesystem storage for development
- Supabase storage for production deployments
Read more about supported blob storage and database options here.
- ESLint for code quality
- Jest for testing
- Docker for containerization
- Make for development scripts
We welcome and appreciate contributions from the community to enhance and expand the capabilities of the Xavia OTA System. Here are some areas where you can contribute:
- New Storage Backends: Implement additional storage backends to provide more options for users.
- Database Support: Add support for other databases like MySQL, MongoDB, etc.
- UI Enhancements: Improve the Admin Dashboard with new features and better user experience.
- Documentation: Help us improve the documentation to make it easier for others to get started and use the system.
- Bug Fixes and Improvements: Identify and fix bugs, and suggest improvements to the existing codebase.
Feel free to fork the repository, make your changes, and submit a pull request. We look forward to your contributions!
Xavia OTA is a free, self-hosted alternative to EAS Updates. While EAS Updates is a managed service that costs massively for growing apps, Xavia OTA can be deployed anywhere and is completely free. Both implement the same expo-updates protocol.
The self-hosted CodePush server is tightly coupled with the Azure ecosystem and requires Azure App Service & Azure Blob Storage for production deployments and an Azurite emulator for local development.
Xavia OTA, on the other hand, is completely independent and can be deployed anywhere - whether that's your own infrastructure, AWS, GCP, or any other cloud provider. Additionally, Xavia OTA implements the expo-updates protocol which is more widely adopted in the React Native ecosystem compared to CodePush's protocol.
This a "yes and no" type of answer. While you can use Xavia OTA with bare React Native apps, you need to configure expo-updates in your app and point it to your Xavia OTA server. Unfortunately, that means you will also need to add a small footprint of the Expo framework to your app as well.
So the "yes" part is for the ability to use Xavia OTA updates with bare React Native apps that haven't been created with Expo, and the "no" part is for the fact that you will need to ship the Expo SDK with your app from now on. The good thing is that you will not need to use any managed Expo services like EAS Build or EAS Submit to use expo-updates in your RN app with Xavia OTA.
[!NOTE] This is fun! This problem might be worth working on by the community. The expo-updates protocol is designed to be agnostic to the underlying SDK that you use to build your app. So it should work with any RN app - no matter how bare-bones it is. The only client-side implementation for expo-updates protocol that we know of is the one made by Expo themselves. Xavia OTA implements the expo-updates protocol on the server side and we would love to see the same on the client side. If you are interested in working on this, here are some pointers:
- Expo-updates protocol specification
- Expo-updates client implementation
Currently, we support:
- Supabase Storage
- Local filesystem storage
More providers (S3, Azure, etc.) are welcome to be implemented by the community. The StorageInterface
is quite simple and you can implement it for any blob storage service.
Currently, we support:
- PostgreSQL
More providers (MySQL, MongoDB, etc.) are welcome to be implemented by the community. The DatabaseInterface
is quite simple and you can implement it for any database service.
Yes! We're using it in production for our own apps. The server implements the complete expo-updates protocol and includes features like release management and rollbacks and simple tracking metrics.
This project is licensed under the MIT License. See the LICENSE file for details.