🔍 Why Even Build Locally?
1️⃣ Expo Cloud Builds cost money
Expo gives a small free quota. After that, you pay per build — which is fine for production, but not for rapid iteration or testing.
Local builds = unlimited free builds.
2️⃣ Android Studio is huge and unnecessary
A full Android Studio install includes:
- IDE
- Emulators
- GUI tools
- Extras you don’t need for CI-style builds
You only need the command-line SDK, build-tools, platform-tools, and NDK.
My setup installs only what is required, trimming the install from 30 GB → ~3 GB.
🛠️ Full Setup Guide (WSL2 Ubuntu 24.04)
✔ Works for Expo, React Native CLI, EAS Build
✔ Matches Expo’s cloud build environment
✔ No Android Studio required
1) Base Dependencies
sudo apt update
sudo apt install -y build-essential git unzip zip curl wget ca-certificates openjdk-17-jdk
2) Node 20.19.4 (matches Expo CI)
Expo’s cloud logs showed Node 20.19.4, so we install that with NVM:
export NVM_DIR="$HOME/.nvm"
if [ ! -d "$NVM_DIR" ]; then
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
fi
source "$NVM_DIR/nvm.sh"
nvm install 20.19.4
nvm alias default 20.19.4
Optional package managers:
npm i -g yarn@1.22.22 pnpm@10.14.0 bun@1.2.20
3) Android SDK + Build-tools + NDK r27b (minimal install)
No Android Studio. Only the components required for building APK/AAB.
Download command-line tools:
export ANDROID_HOME="$HOME/Android/Sdk"
mkdir -p "$ANDROID_HOME"
cd /tmp
wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdtools.zip
mkdir -p "$ANDROID_HOME/cmdline-tools"
unzip -q cmdtools.zip -d "$ANDROID_HOME/cmdline-tools"
mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/tools"
Add to PATH:
export PATH="$ANDROID_HOME/cmdline-tools/tools/bin:$ANDROID_HOME/platform-tools:$PATH"
Accept licenses:
yes | sdkmanager --licenses
Install core packages:
sdkmanager "platform-tools" \
"platforms;android-35" \
"build-tools;35.0.0" \
"build-tools;29.0.3" \
"ndk;27.1.12297006" \
"extras;google;m2repository" \
"extras;android;m2repository"
Set NDK env:
export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/27.1.12297006"
4) Java + Gradle config
Expo uses Java 17 and specific Gradle JVM args:
export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"
export GRADLE_OPTS='-Dorg.gradle.jvmargs="-XX:MaxMetaspaceSize=1g -Xmx4g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" -Dorg.gradle.parallel=true -Dorg.gradle.daemon=false'
5) Expo / EAS CLI + Tools
npm i -g expo-cli eas-cli
Optional but useful:
Maestro:
curl -Ls "https://get.maestro.mobile.dev" | bash
Bundletool:
sudo mkdir -p /opt/bundletool
sudo wget -q https://github.com/google/bundletool/releases/download/1.17.2/bundletool-all-1.17.2.jar -O /opt/bundletool/bundletool.jar
echo 'alias bundletool="java -jar /opt/bundletool/bundletool.jar"' >> ~/.bashrc
6) Add Environment Variables Permanently
Append to ~/.bashrc:
# Android SDK
export ANDROID_HOME="$HOME/Android/Sdk"
export ANDROID_SDK_ROOT="$ANDROID_HOME"
export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/27.1.12297006"
export PATH="$HOME/.nvm/versions/node/v20.19.4/bin:/opt/bundletool:$ANDROID_HOME/build-tools/29.0.3:$ANDROID_HOME/build-tools/35.0.0:$ANDROID_NDK_HOME:$ANDROID_HOME/cmdline-tools/tools/bin:$ANDROID_HOME/platform-tools:$PATH"
# Java
export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"
# Expo Token
export EXPO_TOKEN="<your-expo-token>"
# Gradle
export GRADLE_OPTS='-Dorg.gradle.jvmargs="-XX:MaxMetaspaceSize=1g -Xmx4g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" -Dorg.gradle.parallel=true -Dorg.gradle.daemon=false'
# CI-like behavior
export CI=1
Apply:
source ~/.bashrc
🧪 7) Verify Everything
node -v
npm -v
java -version
sdkmanager --list | head -n 50
bundletool --version
maestro --version
🚀 8) Do a Local EAS Build
Inside your Expo project:
npx eas build --local --platform android --profile production
Now your build runs without consuming Expo credits, and behaves exactly like their cloud runner.
🎯 Final Thoughts
This approach gives you:
- Zero-cost unlimited builds
- A lightweight Android SDK install (no Studio needed)
- A reproducible environment across machines
- Perfect alignment with Expo CI logs
I built this by literally checking Expo’s cloud logs line-by-line, copying the exact versions, and replicating their environment on my local machine.
If you want, I can also generate:
✅ a one-click install script for all of this
✅ a Docker version of the environment
✅ the macOS or Windows-native variant
Just tell me!
This post is edited with AI for clarity and grammar.
Top comments (1)
This is fantastic—“Expo CI cosplay” on WSL2 without paying Expo tax or installing the Android Studio mothership. Love the 30GB → 3GB diet. My SSD just breathed a sigh of relief.