* fix(cli): ensure `~/.cache` is created and `XDG_CACHE_HOME` is set before Next.js loads on Android/Termux to prevent silent HTTP 500 errors due to instrumentation hook failures (#8519) * chore(quality): ignore XDG_CACHE_HOME in the env/docs contract scanner XDG_CACHE_HOME is an XDG Base Directory spec variable set by the OS or the operator, never OmniRoute product config — the same reason XDG_CONFIG_HOME is already ignored. The Android/Termux cache-dir preparation added here reads it to honor an operator-set cache location, which made check-env-doc-sync demand an .env.example/ENVIRONMENT.md entry for a variable we do not own. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * build(pack): require bin/cli/utils/ensureAndroidCacheDir.mjs in the tarball bin/omniroute.mjs imports this module at startup to prepare the Next.js cache dir before serve on Android/Termux. bin/cli/ is only an allowlist PREFIX, so a file missing from the tarball would not fail the unexpected-paths check — it would ship a CLI that throws ERR_MODULE_NOT_FOUND on the very platform this change targets. Registering it makes the absence loud, same guard class as storageKeyProvision.mjs and versionFastPath.mjs. Caught by tests/unit/pack-artifact-entrypoint-closures.test.ts in the v3.8.49 merge-train. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
5.3 KiB
title, version, lastUpdated
| title | version | lastUpdated |
|---|---|---|
| Termux Headless Setup | 3.8.49 | 2026-07-25 |
Termux Headless Setup
OmniRoute can run as a headless server on Android through Termux. The Electron desktop app is not supported in Termux, but the web dashboard and OpenAI-compatible API work from the local browser or from other devices on the same network.
Prerequisites
Install Termux from F-Droid or GitHub releases, then update packages and install the build tools required by native dependencies such as better-sqlite3.
pkg update
pkg upgrade
pkg install nodejs python build-essential git
Node.js version: OmniRoute requires Node
>=22.22.2 <23 || >=24.0.0 <27(matchesenginesinpackage.json/SUPPORTED_NODE_RANGE). Termux'snodejs-ltstypically ships Node 20 LTS, which is no longer supported — installpkg install nodejs(current) instead and verifynode --versionreports a 22.x/24.x+ line.
If native package compilation fails, rerun the pkg install command above and then retry the OmniRoute install.
Install
Run the latest published package directly:
npx -y omniroute@latest
You can also install it globally:
npm install -g omniroute
omniroute
Run
Start OmniRoute in headless server mode:
omniroute
or:
npx omniroute
The dashboard listens on:
http://localhost:20128
Open that URL in the Android browser. If you run clients inside Termux, use the same host and port as the OpenAI-compatible base URL.
Background Execution
For a simple background process:
nohup omniroute > omniroute.log 2>&1 &
To stop it:
pkill -f omniroute
For automatic startup after device boot, install the Termux:Boot add-on and create a boot script:
mkdir -p ~/.termux/boot
cat > ~/.termux/boot/omniroute.sh <<'EOF'
#!/data/data/com.termux/files/usr/bin/sh
cd "$HOME"
nohup omniroute > "$HOME/omniroute.log" 2>&1 &
EOF
chmod +x ~/.termux/boot/omniroute.sh
Android battery optimization can stop long-running background processes. Disable battery optimization for Termux if the server is expected to stay online.
Access From Other Devices
Find the phone IP address on the WiFi network:
ip addr show wlan0
Then open the dashboard from another device:
http://PHONE_IP:20128
For example:
http://192.168.1.50:20128
Keep the phone and client on the same trusted network. If you expose OmniRoute outside the phone, enable API keys and dashboard authentication.
Data Directory
By default OmniRoute stores data under the Termux home directory, following the same server-side data path behavior used on Linux. To place the database somewhere explicit:
export DATA_DIR="$HOME/.omniroute"
omniroute
Limitations
- Electron does not run in Termux.
- There is no system tray or desktop integration.
- This setup is server-only: use the browser dashboard.
- Native dependencies may need local compilation.
- Low-memory Android devices may need fewer concurrent requests.
- MITM/system certificate features may require Android-level trust-store work outside Termux.
Troubleshooting
Unsupported platform: android (every request returns HTTP 500)
Symptom: omniroute / omniroute serve prints ✔ OmniRoute is running!, but every dashboard or API request returns a bare 500 Internal Server Error. ~/.omniroute/logs/application/app.log stays empty, APP_LOG_LEVEL=debug prints nothing useful, and the response body is plain text (Internal Server Error) with no JSON detail.
Cause: Some Termux/Node builds report process.platform === "android". Next.js getCacheDirectory() does not handle that platform: it requires ~/.cache (or a generic tmp dir) to already exist, otherwise it fails while loading the instrumentation hook with:
Error: An error occurred while loading instrumentation hook: Unsupported platform: android
Because the hook never loads, logging never starts — the 500 looks completely undiagnosable. OmniRoute creates ~/.cache (and sets XDG_CACHE_HOME when unset) in the CLI entrypoint before Next.js starts so this probe succeeds on Android/Termux.
Supported resolution (no package patching):
mkdir -p ~/.cache
omniroute serve
On current OmniRoute builds the CLI does this automatically on Android/Termux — a fresh npx -y omniroute@latest / global install should not require the manual step. If you still see the error after upgrading, create ~/.cache once as above and restart.
Do not patch dist/server.js to force process.platform = "linux". That kind of package patch is overwritten on every reinstall/upgrade and is unnecessary once the cache directory exists.
better-sqlite3 Build Errors
Install the Termux build toolchain:
pkg install nodejs python build-essential
Then rerun:
npx -y omniroute@latest
Port Already In Use
Check what is listening on the default port:
ss -ltnp | grep 20128
Stop the old process:
pkill -f omniroute
Dashboard Not Reachable From Another Device
Verify both devices are on the same WiFi network, then test from Termux:
curl http://localhost:20128
If local access works but LAN access does not, check Android hotspot/WiFi isolation and any firewall or VPN profile on the phone.