Skip to content

Releases: mercuretechnologies/xprem

v3.1.0

Choose a tag to compare

@github-actions github-actions released this 01 Aug 16:50
1d0043b

xprem 3.1.0 — Expo Open OTA has a new name

Expo Open OTA is now xprem. Same project, same maintainers, same licenses renamed to respect Expo's trademark. xprem is not affiliated with, sponsored or endorsed by Expo.

The release behind the rename is a big one: the server grows from an update pipeline into a full control plane. Device observability lands with expo-observe support, every device gets an identity you can attach your own attributes to, an MCP server lets agents operate the whole thing over OAuth, and iOS and Android updates published together now move together as publish groups.

The rename: what changes for you

Everything is republished under the new name, and every old name keeps working so nothing breaks on upgrade day:

New (canonical) Old (still published)
Repository mercuretechnologies/xprem redirects automatically
Docker image ghcr.io/mercuretechnologies/xprem ghcr.io/mercuretechnologies/expo-open-ota, ghcr.io/axelmarciano/expo-open-ota
Helm chart oci://ghcr.io/mercuretechnologies/charts/xprem oci://ghcr.io/mercuretechnologies/charts/expo-open-ota (byte-identical copy)
Documentation mercure-technologies.gitbook.io/xprem
CLI npx eoasunchanged

No environment variable, API route or bucket layout changes. Existing deployments upgrade by bumping the tag; switch to the new image and chart names at your own pace.

Highlights

Observability with expo-observe (#119)

xprem is now a self-hosted backend for Expo's expo-observe SDK — point extra.eas.observe.endpointUrl at your server and keep the stock SDK, no fork. Native and JS crashes, cold launch, bundle load, time to first render and time to interactive, sessions, plus your own structured events and logs — all tied to the exact update, branch and channel that produced them, so a regression shows up while the rollout is still on a slice of the branch.

The data lands in your ClickHouse. The dashboard grows an Observe section: overview with a live device-activity globe, per-metric percentiles with breakdowns by device model, OS, region, app version and screen (straight from expo-router or react-navigation), an event explorer and a log stream. Point Grafana, PostHog or Datadog at the same tables, or query them directly.

Device identity (#116)

Every device that checks in is now registered per app: first/last seen, model, OS, current update, branch, runtime version and location, browsable and searchable from the dashboard's Devices view — including a live "online now" count.

On top of the registry, custom device attributes (Enterprise): declare an allowlist of typed keys, then ship $set / $set_once / $unset operations from the app through the expo-observe pipeline. Your plan tier, your tenant, your feature flag — whatever your app knows about the device becomes a first-class filter and breakdown dimension across metrics, events, logs and update health.

MCP server (#141, #142, #143)

xprem is now an MCP server at /mcp. Agents sign in with OAuth 2.1 as dashboard users — dynamic client registration, PKCE, refresh tokens with revocation, no API keys — and every call runs with that user's per-app permissions, nothing more.

16 tools ship under MIT and cover the same operations as the dashboard: list apps, branches, channels and updates, inspect rollouts, create and delete branches and channels, roll back, republish. 10 more come with the Enterprise edition and open up the observability dataset: update health, metric breakdowns, events, logs, audit logs and device search.

"Which screens had the worst time to interactive since 3.4.2 rolled out?"

"Something looks wrong since the last release. Roll production back to the previous update."

Publish groups (#118)

One eoas publish run produces an iOS update and an Android update; they are now linked by a publish group. The dashboard collapses them into a single row with aggregated health across both platforms, and republish and rollback act on the whole group, so putting an old version back can never leave the branch serving one platform's build without the other. Available from the dashboard, the REST API and the MCP tools; older CLIs keep publishing ungrouped rows.

Republish and roll back from the dashboard (#127)

Rollback and republish are no longer CLI-only: revert a branch to its previous update, or put any past update (or publish group) back live, in one click from the Updates feed.

GeoIP (#147)

Two ways to locate your fleet: trust the visitor-location headers your CDN already adds (Cloudflare, CloudFront, Vercel, or custom X-Geo-* headers), or give the server free MaxMind GeoLite2 credentials and it downloads and refreshes the database itself — nothing to mount. Location feeds the live device map and makes region a breakdown dimension everywhere. Configure neither and everything else keeps working.

Server configuration wizard (#146)

npx eoas server:init walks through the whole server setup — storage backend, delivery, database, cache, key store, GeoIP, replicas — and generates a ready-to-run .env file for Docker, or values.yaml plus a properly gitignored secrets file for Helm. It reuses your existing master key on re-run, warns you to back it up when minting one, and npx eoas server:validate checks a config before you deploy it.

Faster on the hot path, and measured (#145, #148)

Manifest signatures are now cached (keyed by content hash, so a stale signature can never be served), alongside short-TTL caches for app config and channel mappings. A new S3 presigned URL delivery mode serves assets straight from a private bucket with no CDN in front and no traffic through the server.

The release also ships a reproducible k6 load test with published results: one 1-vCPU instance serving real expo-updates polls from 100,000 devices, code signing and telemetry on — 938 req/s at the peak of a full-fleet rollout, zero errors. Method and raw data in test/load/results.

Security hardening

  • Sensitive endpoints (sign-in, token issuance, uploads) are rate limited (#131).
  • Dashboard sessions can be revoked server-side, and refresh tokens rotate with session-version invalidation (#133).
  • API tokens carry specific roles instead of blanket access (#141).
  • Upload requests are validated harder before touching storage (#135).
  • GitHub workflows run with read-only permissions by default (#128).

Also in this release

  • DISABLE_DEVICE_TELEMETRY=true switches off the device registry and telemetry ingest entirely, for deployments that want none of it (#134).
  • Overwrite confirmation in eoas before replacing existing config, and safer write modes (#129).
  • Dashboard polish: debounced filters, better loading skeletons, richer update details (5d517aa).
  • pgx bumped to 5.9.2 (#110).

Install or upgrade

  • Docker: ghcr.io/mercuretechnologies/xprem:v3.1.0
  • Helm: helm install xprem oci://ghcr.io/mercuretechnologies/charts/xprem --version 3.1.0
  • CLI: npx eoas@3

Observability, identity and the control plane need PostgreSQL (control plane mode); stateless mode keeps working with nothing but a bucket.

Full changelog: v3.0.5...v3.1.0

v3.0.5

Choose a tag to compare

@github-actions github-actions released this 22 Jul 09:49
b39c175

What's Changed

Changes

  • Docker image: ghcr.io/mercuretechnologies/expo-open-ota:v3.0.5
  • Helm chart: helm install expo-open-ota oci://ghcr.io/mercuretechnologies/charts/expo-open-ota --version 3.0.5

Full Changelog: v3.0.4...v3.0.5

v3.0.4

Choose a tag to compare

@github-actions github-actions released this 21 Jul 09:27
aeb43dc

Changes

  • Docker image: ghcr.io/mercuretechnologies/expo-open-ota:v3.0.4
  • Helm chart: helm install expo-open-ota oci://ghcr.io/mercuretechnologies/charts/expo-open-ota --version 3.0.4

What's Changed

  • Support TypeScript for EoAS init and add DISABLE_CODE_SIGNING conditions by @axelmarciano in #103

Full Changelog: v3.0.3...v3.0.4

v3.0.3

Choose a tag to compare

@github-actions github-actions released this 20 Jul 19:57
83deafe

Changes

  • Docker image: ghcr.io/mercuretechnologies/expo-open-ota:v3.0.3
  • Helm chart: helm install expo-open-ota oci://ghcr.io/mercuretechnologies/charts/expo-open-ota --version 3.0.3

What's Changed

Full Changelog: v3.0.2...v3.0.3

v3.0.2

Choose a tag to compare

@github-actions github-actions released this 20 Jul 12:50
d1c74e2

Changes

  • Docker image: ghcr.io/mercuretechnologies/expo-open-ota:v3.0.2
  • Helm chart: helm install expo-open-ota oci://ghcr.io/mercuretechnologies/charts/expo-open-ota --version 3.0.2

What's Changed

Full Changelog: v3.0.1...v3.0.2

v3.0.1

Choose a tag to compare

@github-actions github-actions released this 20 Jul 10:38
a71a540

Changes

  • Docker image: ghcr.io/mercuretechnologies/expo-open-ota:v3.0.1
  • Helm chart: helm install expo-open-ota oci://ghcr.io/mercuretechnologies/charts/expo-open-ota --version 3.0.1

What's Changed

  • feat: generalize generic CDN to any cloud storage via CDN_BASE_URL by @axelmarciano in #96

Full Changelog: v3.0.0...v3.0.1

v3.0.0

Choose a tag to compare

@github-actions github-actions released this 20 Jul 07:10
f173c6c

Expo Open OTA v3

v3 is the largest release since the project started. The server now hosts all your Expo apps behind a single deployment, with a web dashboard, progressive rollouts, A/B testing and an enterprise edition built on the same open-source core. It has been serving production traffic throughout the beta, to apps totaling more than a million monthly active users.

Coming from v2? Read the migration guide before upgrading, this release contains breaking changes.

Highlights

Multi-app support

One server hosts all your Expo apps. Each app gets its own branches, channels, API tokens and update history, and no Expo account is required anymore.

Control plane mode and the dashboard (#65, #87)

Plug in PostgreSQL and the server migrates itself into control plane mode: a web dashboard where your team signs in with individual accounts to manage apps, channels, tokens and rollouts. Stateless mode still works with nothing but a bucket and a few environment variables, and remains the simplest way to get started.

Progressive rollouts (#91)

Ship an update to 10% of devices, watch your metrics, then increase, finish or revert in one click from the dashboard, or from the CLI with npx eoas publish --branch production --rollout-percentage 10.

A/B testing

A channel can serve two branches at once, with devices split deterministically between them. Test two variants in production and promote the winner.

Enterprise edition (#88, #89, #90, #94)

For teams that need tighter control, the Enterprise edition adds single sign-on through any OIDC provider (Microsoft Entra ID, Okta, Google Workspace, Keycloak...), protected branches that only explicitly allowed tokens can publish to, and per-token IP allowlists. Everything else stays MIT-licensed and free.

Breaking changes

  • Apps now identify themselves with the expo-app-id request header instead of the server-side EXPO_APP_ID environment variable. Add it to updates.requestHeaders in your app config and rebuild.
  • The bucket layout now includes the app id. The re-path runs automatically on first v3 boot and needs delete permission on the bucket (s3:DeleteObject on S3, roles/storage.objectAdmin on GCS). The server answers 503 until it completes.
  • Publishing requires eoas v3: publish routes moved under /{appId}/.
  • Dashboard sign-in now takes ADMIN_EMAIL together with ADMIN_PASSWORD.
  • S3_KEY_PREFIX is renamed to BUCKET_KEY_PREFIX (the old name still works with a deprecation warning).
  • Prometheus metrics carry an appId label, and update_error_users_total now counts unique clients.

The migration guide walks through both paths, staying stateless or moving to control plane mode.

Also in this release

  • Readiness and liveness probes so orchestrators gracefully (#93)
  • PostgreSQL-backed stores with full test coverad to Go 1.25
  • The repository moved to [mercuretechnologies/eub.com/mercuretechnologies/expo-open-ota). Images
    and charts are published to both ghcr.io/mercuracy ghcr.io/axelmarciano` namespace, so
    existing deployments keep receiving updates with

Install or upgrade

  • Docker: `ghcr.io/mercuretechnologies/expo-open
  • Helm: helm install expo-open-ota oci://ghcr.its/expo-open-ota --version 3.0.0
  • CLI: npx eoas@3

Full changelog: https://github.com/mercureteompare/v2.3.22...v3.0.0

v3.0.0-beta.7

v3.0.0-beta.7 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 19 Jul 12:15
c0c154f

Changes

  • Docker image: ghcr.io/mercuretechnologies/expo-open-ota:v3.0.0-beta.7
  • Helm chart: helm install expo-open-ota oci://ghcr.io/mercuretechnologies/charts/expo-open-ota --version 3.0.0-beta.7

v3.0.0-beta.6

v3.0.0-beta.6 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 19 Jul 11:08

Changes

  • Docker image: ghcr.io/mercuretechnologies/expo-open-ota:v3.0.0-beta.6
  • Helm chart: helm install expo-open-ota oci://ghcr.io/mercuretechnologies/charts/expo-open-ota --version 3.0.0-beta.6

v3.0.0-beta.4

v3.0.0-beta.4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 19 Jul 11:01
2b4742d

Changes

  • Docker image: ghcr.io/mercuretechnologies/expo-open-ota:v3.0.0-beta.4
  • Helm chart: helm install expo-open-ota oci://ghcr.io/mercuretechnologies/charts/expo-open-ota --version 3.0.0-beta.4