expo/builder
docs

Documentation

Everything to go from a fresh machine to a signed APK. For the exhaustive reference, see the full README.

Quick start

Install via the hosted APT repo (recommended — picks up new releases automatically):

bash
curl -fsSL https://41vi4p.github.io/expo-builder-local/apt/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/ebl-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/ebl-archive-keyring.gpg] https://41vi4p.github.io/expo-builder-local/apt stable main" | sudo tee /etc/apt/sources.list.d/ebl.list
sudo apt update && sudo apt install ebl

Or the one-line installer — see the Download page for every option.

Then:

bash
ebl setup     # checks/installs Docker, pulls the runner/orchestrator/web images
ebl config    # interactive: your projects folder, Expo token, ports
ebl start     # runs the orchestrator + web GUI as containers, prints the GUI link

cd /path/to/your/expo/app
ebl build .              # signed APK, auto engine
ebl build . --prod       # shortcut for --artifact aab --profile production

ebl build never needs setup/config/start — it works standalone, from anywhere, against any Expo project, talking to Docker directly. Those three commands are only for the optional web GUI (live dashboard, build history, keystore manager).

Commands

ebl setupOne-time: checks Docker is installed and running (offers to install it if not), then pulls the runner/orchestrator/web images.
ebl configInteractive wizard: projects folder, a default Expo token plus optional per-account tokens, orchestrator/web ports.
ebl startRuns the orchestrator + web GUI as Docker containers, waits for both to report healthy, prints the GUI URL.
ebl stopStops and removes those two containers. Build history/keystores live in a separate volume and are preserved.
ebl build [path]Builds an Expo project. Works completely standalone — no setup/config/start required.

Run ebl <command> --help for the full option list of any command.

Build engines

EngineHowExpo account?
Gradle (local)expo prebuild generates the native android/ project, then Gradle compiles it directly in the container.No — fully offline once dependencies are cached.
EAS (local)eas build --local — the same command EAS's own cloud workers run, just on your machine.Yes — needs an Expo access token.
Auto (default)Uses EAS if the project has an eas.json and a token is available, otherwise falls back to Gradle.Optional.

Multiple Expo accounts

If your apps aren't all under the same EAS account, save one token per account instead of juggling --expo-token/EXPO_TOKEN by hand — ebl build auto-selects the right one by matching the project's app.json expo.owner field.

Resolution order: --expo-token/EXPO_TOKEN (explicit override) → a .ebl-tokenfile in the project root → the saved token for this project's owner → the default token from ebl config. If none resolve and the engine needs one, you're prompted interactively, with the option to save it to .ebl-token (auto-added to .gitignore).

Signing

Debug— every build is signed with Expo's default debug keystore. Good for a test device, not accepted by the Play Store.

Release — provide a real keystore (.jks/.keystore) via --keystore on the CLI, or upload once in the GUI's keystore manager. The password/alias are AES-256-GCM encrypted at rest and only decrypted in memory for the one build that uses them — nothing persists in your project folder after the build finishes.

Security notes

  • Both services bind to 127.0.0.1 by default.
  • Anything that looks like a secret in your .env/eas.json/google-services.json is redacted from streamed and persisted build logs.
  • ebl config's saved settings live at ~/.config/ebl/config.json (0600), secrets AES-256-GCM-encrypted using a machine-local key that never leaves the machine.
  • Every uploaded keystore stays inside Docker-managed storage or is deleted at the end of a build.

Troubleshooting

ebl setup says Docker isn't reachable after installing it
Log out and back in (or run newgrp docker) so your user session picks up docker-group membership, then re-run ebl setup.
"Path is outside the configured allowed roots" (GUI)
The projects folder set via ebl config doesn't cover the folder you picked.
Build hangs at "Install"
First build for a project downloads its full node_modules; later builds reuse the shared caches and are much faster.
"eas build --local failed" / credential errors
The EAS engine needs a real Expo access token (ebl config, EXPO_TOKEN, or --expo-token), and a valid eas.json profile.
AAB isn't accepted by the Play Store
Make sure you built with Release signing and a real upload keystore, not the debug default.