English Documentation | 中文文档
This repository contains a BUN server that implements the Expo Updates protocol specification.
Important
This repository provides a basic demonstration of how the protocol can be converted into code. There is no guarantee that it is complete, stable, or performant enough to be used as a complete backend for expo-updates.
I do not provide technical support for such custom expo-updates server implementations.
Expo provides a set of services called EAS (Expo Application Services), which includes EAS Update, allowing you to host and serve updates for Expo applications using the expo-updates library.
In some cases, such as being unable to afford EAS services or having your main users in China, you might need more precise control over how updates are delivered to your application. One option is to implement a custom update server that complies with the specification to provide update manifests and assets.
- Runtime Environment: Bun
- Web Framework: Elysia
- Development Language: TypeScript
- OSS: Dogecloud Object Storage (S3 protocol)
- Cache: In-memory cache (no Redis required)
bun-expo-updates-server/
├── .gitignore
├── README.md
├── README.zh-CN.md
├── bun.lock
├── package.json
├── .env.example # Environment variable example file
├── updates/ # Update file storage directory
├── logs/ # Log files
├── src/
│ ├── index.ts # Application entry file
│ ├── modules/ # Core modules
│ │ └── manifest.ts # Manifest processing module
│ ├── config/ # Configuration files
│ │ └── oss-config.example.ts
│ ├── code-sign-keys/ # Code signing keys
│ ├── test/ # Test files
│ │ └── utils/ # Utility tests
│ ├── scripts/ # Script files
│ │ ├── upload.sh # Version update script
│ │ ├── exportClientExpoConfig.ts # Export Expo client config script
│ │ ├── updateMime.ts # Fix MIME type script
│ │ └── uploadUpdatesToOSS.ts # Upload updates to OSS script
│ └── utils/ # Utilities
│ ├── helper-oss.ts # OSS helper functions
│ ├── logger.ts # Logging tool
│ ├── util.ts # General utility functions
│ └── oss-provider/ # OSS providers
│ ├── dogecloud-adapter.ts # Dogecloud adapter
│ ├── s3-adapter.ts # S3 adapter
│ ├── factory.ts # Factory pattern adapter
│ └── types.ts # OSS provider type definitions
└── tsconfig.json- Runtime version: String type. Specifies the underlying native code version on which the app runs. When updates depend on new or changed native code (such as updating the Expo SDK or adding native modules), the runtime version needs to be updated.
- Platform: "ios" or "android". Specifies the platform for which updates are provided.
- Manifest: Object described in the protocol. Contains assets and other details needed for Expo applications to load updates.
-
Install dependencies and start the server Run the following commands in the project root directory:
bun install bun run dev
The server will start at http://localhost:3000.
-
Configure Environment Variables Create a
.envfile and configure the following variables:# Log Settings # Enable debug logs DEBUG=true # Log language setting (zh_CN/en_US) LOG_LANGUAGE=en_US # Object Storage Service Configuration # OSS provider OSS_PROVIDER=your_oss_provider # OSS access key OSS_ACCESS_KEY=your_access_key # OSS secret key OSS_SECRET_KEY=your_secret_key # Force path style (0 false, 1 true) OSS_FORCE_PATH_STYLE=0 # OSS region # OSS_REGION=your_region # OSS bucket name # OSS_BUCKET=your_bucket # OSS endpoint # OSS_ENDPOINT=your_endpoint # Client Project Path # Local path to the client project CLIENT_PROJECT_PATH=/path/to/your/client/project # Private Key Path Configuration # Path to the private key for code signing PRIVATE_KEY_PATH=code-sign-keys/private-key.pem # Server Port Configuration # Port on which the server listens port=3001 # Update Resource Download URL (OSS or CDN) # Base URL for update resources HOSTNAME=https://your-update-domain.com
-
Build the Project Run the following commands in the project root directory:
bun install # Build the project # Choose the appropriate target for your server architecture # Example: bun-linux-x64 bun build \ --compile \ --minify \ --target bun-linux-x64 \ --outfile server \ ./src/index.ts
--target OS Architecture haswellarchitecturenehalemarchitecturebun-linux-x64 Linux x64 ✅ ✅ bun-linux-arm64 Linux arm64 ✅ N/A bun-windows-x64 Windows x64 ✅ ✅ bun-windows-arm64Windows arm64 ❌ ❌ bun-darwin-x64 macOS x64 ✅ ✅ bun-darwin-arm64 macOS arm64 ✅ N/A -
Start the Server
- Run the following commands in the same directory as the
serverfile:
# Grant execute permission chmod +x server mkdir -p logs # Start the server ./server
-
The server will start at http://localhost:3001.
-
Using pm2 to manage the binary file
- Run the following commands in the same directory as the
serverfile:
- Run the following commands in the same directory as the
# Grant execute permission chmod +x server mkdir -p logs- Create an
ecosystem.config.jsfile:
module.exports = { apps: [ { name: "bun-updates", script: "./server", env: { // Log Settings // Enable debug logs "DEBUG": "true", // Log language setting (zh_CN/en_US) "LOG_LANGUAGE": "en_US", // Object Storage Service Configuration // OSS provider "OSS_PROVIDER": "your_oss_provider", // OSS access key "OSS_ACCESS_KEY": "your_access_key", // OSS secret key "OSS_SECRET_KEY": "your_secret_key", // Force path style (0 false, 1 true) "OSS_FORCE_PATH_STYLE": "0", // OSS region // "OSS_REGION": "your_region", // OSS bucket name // "OSS_BUCKET": "your_bucket", // OSS endpoint // "OSS_ENDPOINT": "your_endpoint", // Client Project Path // Local path to the client project "CLIENT_PROJECT_PATH": "/path/to/your/client/project", // Private Key Path Configuration // Path to the private key for code signing "PRIVATE_KEY_PATH": "code-sign-keys/private-key.pem", // Server Port Configuration // Port on which the server listens "port": "3001", // Update Resource Download URL (OSS or CDN) // Base URL for update resources "HOSTNAME": "https://your-update-domain.com" } } ] }
Run the following commands in the same directory as
ecosystem.config.js:pm2 start pm2 logs bun-updates
- Run the following commands in the same directory as the
-
Configure Expo Application Ensure your Expo application is configured to load updates from your custom server. Set in your app's app.json file:
{ "expo": { "updates": { "url": "http://your-server-url.com/api/manifest", "enabled": true, "checkAutomatically": "ON_LOAD" } } } -
Export and Upload Updates Use the scripts provided in the project to export application updates and upload them to object storage:
# Export Expo client ./src/scripts/export-client.sh # Upload updates to object storage bun run src/scripts/uploadUpdatesToOSS.ts
Alternatively, you can use the command in
package.json:bun up
to generate and upload the hot update package.
-
Access Updates Client applications will automatically check for and download updates through the
/api/manifestendpoint.
The server currently provides the following API endpoints:
GET /api/manifest: Provides Expo update manifests- Supported parameters:
expo-protocol-version: Header parameter, supports versions 0 and 1expo-platform: Header parameter, value is "ios" or "android"expo-runtime-version: Header parameter, specifies the runtime versionexpo-current-update-id: Header parameter, ID of the client's current updateexpo-embedded-update-id: Header parameter, ID of the embedded update in the applicationexpo-expect-signature: Header parameter, if set, the response will be signed
- Responses:
- Normal update: Returns a multipart/mixed response containing the latest update manifest and resource information
- Rollback update: Returns a multipart/mixed response with rollback instructions
- No update: Returns a response indicating that no update is available
- Supported parameters:
This server is created using Bun and the Elysia framework, supporting Object Storage (OSS) functionality to manage update files. The main entry file is located at src/index.ts, and the core update handling logic is in src/modules/manifest.ts.
The server supports the following features:
- Multi-platform update support (iOS and Android)
- Update management based on runtime version
- Rollback mechanism
- Code signature verification
- Object Storage (OSS) integration
- Logging
You can also deploy this server using Docker:
docker pull istrih/bun-expo-updates-server:latest
docker run -p 3000:3000 \
-e OSS_PROVIDER=your_oss_provider \
-e OSS_ACCESS_KEY=your_access_key \
-e OSS_SECRET_KEY=your_secret_key \
-e DEBUG=true \
-e LOG_LANGUAGE=en_US \
-e HOSTNAME=https://your-update-domain.com \
istrih/bun-expo-updates-server:latestThis project is licensed under the GPL-3.0-or-later License.
