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):
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 eblOr the one-line installer — see the Download page for every option.
Then:
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 productionebl 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 setup | One-time: checks Docker is installed and running (offers to install it if not), then pulls the runner/orchestrator/web images. |
| ebl config | Interactive wizard: projects folder, a default Expo token plus optional per-account tokens, orchestrator/web ports. |
| ebl start | Runs the orchestrator + web GUI as Docker containers, waits for both to report healthy, prints the GUI URL. |
| ebl stop | Stops 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
| Engine | How | Expo 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.1by default. - Anything that looks like a secret in your
.env/eas.json/google-services.jsonis 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.