Termux on Android (Non-Root): Complete Setup & Optimization Guide

Termux on Android (Non-Root): Complete Setup & Optimization Guide

TL;DR: Turn any Android 7.0+ phone into a Linux lab without root. This guide covers the official install (F-Droid or GitHub — skip the restricted Play Store build), first-run configuration, essential packages, proot-distro containers, and the honest truth about memory and swap. You'll need Android 7.0+, roughly 5 GB free storage, and a willingness to read /proc/swaps before trusting anyone's "free RAM" trick.


Two hours into "optimizing" a fresh Termux install, I was still smug. I'd created a 2 GB swap file, mkswap had formatted it clean, swapon had… waited. Operation not permitted. I had just executed the exact steps half the tutorials on the internet tell you to run — and the kernel had told me to sit down.

That's the thing about Termux: it's a real Linux userspace, and a real Linux kernel says no to you when you have no root. The good news: almost everything that matters still works without it. This is the version of the guide I wish I'd read first — install, first-run config, containers, memory facts, and SSH — every claim checked against stock Android, August 2026.

Install Termux from Official Sources Only (Skip the Play Store)

The Play Store situation changed while most tutorials weren't looking. Termux got pulled from Google Play in 2021, then quietly returned in June 2024 — but as an unofficial, restricted fork. The core team's own announcement calls the Play Store release "functionally equivalent to v0.108", with ten releases of bug and security fixes reverted, reduced permissions, and no RUN_COMMAND intent. It's Android 11+ only, and the team still lists F-Droid and GitHub as the only official sources.

⚠ The Play Store build is a forked release source maintained outside the core team (github.com/termux-play-store). Features are missing, fixes are reverted, and it may be taken down if it keeps violating Play policy. Install it at your own risk — or just don't.

Option 1: F-Droid (Recommended)

F-Droid carries the actively maintained app and the whole plugin ecosystem, all signed and updated from one repo. As of this writing the latest stable is 0.118.3, with 0.119.0-beta.3 available if you like living on the edge.

bash
# On your Android device, open F-Droid and search "Termux"
# Install all of these from the SAME source (F-Droid):
# - Termux        (main app)
# - Termux:API    (hardware access: camera, GPS, sensors, clipboard)
# - Termux:Boot   (run scripts on device boot)
# - Termux:Widget (home-screen shortcuts)

Why F-Droid wins: automatic updates, every plugin in one repo, no Google Play Services dependency, and a signed build the Termux team controls.

Option 2: GitHub Releases (Direct APK)

Can't use F-Droid? Grab the current stable from the official repo. The naming pattern is termux-app_v<version>+github-debug_<arch>.apk — not the _apk-<arch> format floating around in older guides.

bash
# Visit: https://github.com/termux/termux-app/releases
# Download: termux-app_v0.118.3+github-debug_arm64-v8a.apk
# (match the suffix to your architecture — see table below)

# Verify the hash before installing — the release ships a checksum file:
# grep arm64-v8a termux-app_v0.118.3+github-debug_sha256sums | sha256sum -c -

Architecture mapping:

Device ArchitectureAPK Suffix
ARM64 (most modern phones)arm64-v8a
ARM32 (older devices)armeabi-v7a
x86_64 (emulators, Chromebooks)x86_64
x86 (old emulators)x86

Enable Unknown Sources & Install

bash
# Settings → Security → Install unknown apps → [Your browser / F-Droid] → Allow
# Open the downloaded APK → Install

Pro tip: on Android 13+ you'll hit a "Restricted settings" warning. That's normal — Termux needs unrestricted battery usage for background jobs (sshd, cron). Grant it: Settings → Apps → Termux → Battery → Unrestricted.

⚠ One source, all apps. Every Termux app shares the sharedUserId com.termux and must be signed with the same key. Never mix F-Droid and GitHub builds — plugins will silently refuse to talk to the main app and you'll end up uninstalling everything. Pick F-Droid or GitHub for the app and every plugin.

First Run: Updates, Storage & the Filesystem Layout

Launch Termux. You land in $HOME (/data/data/com.termux/files/home). Do these in order — they're cheap and they prevent 90% of the "why is nothing working" threads on r/termux.

1. Update the Package Index & Upgrade

termux
pkg update && pkg upgrade -y

Expected output: tens to hundreds of packages upgraded. First run takes 2–5 minutes on decent hardware. If you see repository errors, run termux-change-repo and pick a mirror close to you.

2. Grant Storage Access

termux
termux-setup-storage

Tap "Allow" on the system dialog. The script broadcasts an intent to the app, which then rebuilds the symlink tree in $HOME:

  • ~/storage/shared → shared storage
  • ~/storage/downloads/sdcard/Download
  • ~/storage/dcim/sdcard/DCIM
  • ~/storage/music, ~/storage/pictures, ~/storage/movies

Gotcha: on Android 11+ scoped storage, the symlinks are the only sane way in — raw /sdcard/... writes break in ways that are painful to debug. Revoked the permission later? The symlinks go dead. Re-grant it in Settings → Apps → Termux → Permissions, then re-run termux-setup-storage — it rebuilds the whole tree from scratch.

3. Know Your Filesystem

PathPoints toWhat lives there
$PREFIX/data/data/com.termux/files/usrInstalled packages — treat as read-only
$HOME/data/data/com.termux/files/homeYour scripts, configs, data
$TMPDIR/data/data/com.termux/files/usr/tmpTemp files
~/storage/sharedAndroid shared storageFiles visible to other apps

Key insight: $PREFIX belongs to the package manager. Your stuff goes in $HOME. Writing into $PREFIX by hand gets silently clobbered on the next upgrade — I've lost a dotfile collection that way.

4. Shell Setup

termux
# Default shell is bash
echo $SHELL

# Optional: zsh + oh-my-zsh
pkg install zsh git -y
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
chsh -s zsh

Pro tip: keep bash as the default for script compatibility and hop into zsh interactively with exec zsh when you want the pretty prompt. chsh ships with termux-tools, so this just works.

Essential Packages: Build Your Mobile Toolkit

One command, the whole foundation:

termux
pkg install -y \
  git curl wget \
  vim nano \
  htop tree \
  zip unzip \
  openssh \
  python nodejs \
  build-essential \
  proot-distro \
  termux-api

Package Breakdown

PackagePurposeWhen You'll Use It
gitVersion controlCloning repos, CTF tools, dotfiles
curl/wgetHTTP clientsDownloading scripts, API testing
vim/nanoEditorsConfig editing, quick scripts
htopProcess monitorFinding the memory hog before it finds you
treeDirectory visualizationNavigating project structures
zip/unzipArchivesCTF challenges, file transfer
opensshSSH client/serverRemote access, Git over SSH
pythonScriptingExploit dev, tooling, data parsing
nodejsJavaScript runtimeWeb tools, modern CLI apps
build-essentialToolchain metapackageclang + make + pkg-config for compiling
proot-distroLinux distro containersFull Ubuntu/Kali/Arch userspaces, no root
termux-apiAndroid hardware bridgesWiFi info, clipboard, battery, sensors

Note on termux-api: the package (currently v0.59.1) installs the CLI scripts, but the commands only talk to hardware if you also install the Termux:API app from the same source. Same rule as everything else: F-Droid app + F-Droid package, or GitHub + GitHub.

Verify the Install

termux
git --version
python3 --version
node --version
ssh -V
proot-distro --help
termux-clipboard-get     # needs the Termux:API app installed

Run Full Linux Distros with proot-distro (No Root)

proot-distro is at v5.6.0 (August 2026), and it changed shape: it's now an OCI-image tool — think docker pull without the daemon. Containers are assembled from Docker Hub images, and a bunch of old flag names are gone. The good news: it's simpler.

termux
# Browse Docker Hub from the terminal
proot-distro search ubuntu

# Ubuntu (pin the LTS if you want stability)
proot-distro install ubuntu

# Kali — the OFFICIAL image name is kalilinux/kali-rolling
# (a bare `install kali` does not resolve on Docker Hub)
proot-distro install kalilinux/kali-rolling

# Arch — official image, rolling and minimal
proot-distro install archlinux

Truth bomb about Kali: the official image ships no tools by default. "Pentesting tools pre-installed" is a myth from the old rootfs-based builds. Inside Kali, run apt update && apt install -y kali-linux-headless (or just install the specific tool you need — nmap, metasploit-framework, whatever). Cleaner and faster than pulling the kitchen sink.

Enter a Distro

termux
# Interactive shell (you're root inside by default)
proot-distro login ubuntu

# Explicit — the default anyway
proot-distro login ubuntu --user root

# One command, multi-step — wrap in bash -c so && runs INSIDE the distro
proot-distro login ubuntu -- bash -c "apt update && apt install -y nmap"

# Share Termux's tmp as /tmp inside the container
proot-distro login ubuntu --shared-tmp

# Bare-minimum proot: only /dev, /proc, /sys — for weak kernels or tight RAM
proot-distro login ubuntu --minimal

Rabbit hole I fell into: proot-distro login ubuntu -- apt update && apt install -y nmap runs apt install on the host after the login exits — a classic "why is this in my Termux home?" moment. The -- separator passes a command into the container's shell, so anything more than one command needs bash -c "...".

Persistent Aliases

termux
# Add to ~/.bashrc (or ~/.zshrc)
alias ubuntu='proot-distro login ubuntu'
alias kali='proot-distro login kalilinux/kali-rolling'
alias ubuntu-root='proot-distro login ubuntu --user root'

Now ubuntu drops you into a real Ubuntu userspace with apt, gcc, and all the toys — no kernel modules, no root, no ROM surgery.

Memory on Non-Root Android: The ZRAM & Swap Reality Check

Here's where I ate my words — and where most Termux guides lie to you. On stock, non-rooted Android you cannot add swap space. Period.

  • mkswap and swapon do ship inside Termux's util-linux package — but the swapon(2) syscall demands CAP_SYS_ADMIN, and Android's SELinux policy denies it to the untrusted_app domain. You get Operation not permitted.
  • Writing to /sys/block/zram0/* or running modprobe zram? Root. Full stop.
  • Android already runs ZRAM at the kernel level on most devices — it's configured by init scripts, not by you.

⚠ Swap on stock Android needs root. The "swap file without root" tutorials you'll find are either outdated, or they quietly assume a vendor ROM. Some devices (notably Xiaomi/HyperOS with "Memory Extension") do permit unprivileged swapon — but that's undocumented, kernel-specific behavior, and one widely-reported case left a persistent 6 GB ZRAM allocation the owner could not remove. Don't build your workflow on it.

What Actually Works Non-Root: Check, Then Shrink

termux
# Look at what the kernel already set up (read-only, no root needed)
cat /proc/swaps
swapon --show
zramctl              # zram devices, listed read-only

If ZRAM shows up here, it's already working — Android's memory manager (LMKD) will swap pages into it under pressure. Your job is to make the pressure smaller:

  • Run a lighter distro: proot-distro install alpine instead of Ubuntu.
  • Log in with --minimal to drop the heavy host bindings.
  • Close background Android apps — real RAM, zero magic.
  • Watch htop inside Termux and kill the leak instead of band-aiding it.

Root-Only Option: A Real Swap File

Rooted device? Then — and only then — swap is on the table. Run these from a root shell (Magisk's su or Termux's tsu), not plain Termux:

root
# From a ROOT shell (tsu or Magisk su) — fails on stock Android
dd if=/dev/zero of=/data/local/tmp/swapfile bs=1M count=2048
mkswap /data/local/tmp/swapfile
swapon /data/local/tmp/swapfile

# Verify
cat /proc/swaps

⚠ Rooted only. Skip this section on a stock phone. Even with root, a swap file on flash wears the eMMC and is slower than ZRAM — if your ROM already runs ZRAM, you're done; if it doesn't, buy a phone with more RAM instead of grinding your storage into virtual memory.

Keep Termux Alive: Battery Exemptions, Wake Locks & Boot Scripts

Android kills background apps. That's the #1 reason sshd "disappears" mid-session. Three layers of defense, in order:

1. Battery Exemptions (Android Settings)

bash
# Settings → Apps → Termux → Battery → Unrestricted
# Settings → Apps → Termux:API → Battery → Unrestricted
# Settings → Apps → Termux:Boot → Battery → Unrestricted

2. Wake Lock (Terminal)

termux
termux-wake-lock      # hold a wakelock so the CPU stays alive in background
termux-wake-unlock    # release it when you're done

3. Termux:Boot Script (Device Boot)

termux
mkdir -p ~/.termux/boot
cat > ~/.termux/boot/start-sshd << 'EOF'
#!/data/data/com.termux/files/usr/bin/bash
# Grab a wake lock and bring up sshd at device boot
termux-wake-lock
sshd
EOF
chmod +x ~/.termux/boot/start-sshd

Cleaner alternative: runit services. pkg install termux-services -y, then sv-enable sshd — it supervises the daemon and restarts it if it dies, which a boot script won't.

SSH Daemon on Port 8022: Make Your Phone a Server

Termux's OpenSSH (currently 10.5p1) listens on port 8022 by default — port 22 is privileged, and you're not root. Key-only auth, bind it to your WiFi IP, done right.

Start the Daemon

termux
# Generate a keypair (first time only)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""

# Start sshd
sshd

# Confirm it's listening
ss -tln | grep 8022        # or: netstat -tlnp | grep 8022 (install net-tools)

Connect from Another Device

bash
# On your laptop — replace username and IP
ssh -p 8022 u0_a123@192.168.1.50

# Find your username (run on the phone)
whoami                    # e.g. u0_a123

# Find the phone's IP — robust: field order in `ip route get` varies
ip route get 1.1.1.1 | awk '{for (i=1; i<=NF; i++) if ($i == "src") print $(i+1)}'

# Or via Termux:API (JSON output — needs jq installed)
termux-wifi-connectioninfo | jq -r .ip

Why not awk '{print $7}'? Some iproute2 builds inject proto dhcp or other fields before src, shifting the column. Scanning for the src token is build-proof — I learned that the hard way on a vendor ROM.

Harden sshd_config

The config lives at $PREFIX/etc/ssh/sshd_confignot ~/.ssh/, which is a mistake a lot of guides make. Drop in a hardened version with your real username baked in:

termux
# Back up the stock config first — package upgrades will leave your file
# alone, but you still want a way back
cp "$PREFIX/etc/ssh/sshd_config" "$PREFIX/etc/ssh/sshd_config.bak"

# Bake in your username — unquoted heredoc expands it
ALLOWED_USER="$(whoami)"
cat > "$PREFIX/etc/ssh/sshd_config" <<EOF
Port 8022
AddressFamily inet
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
KbdInteractiveAuthentication no
UsePAM no
Compression yes
ClientAliveInterval 30
ClientAliveCountMax 4
SyslogFacility AUTH
LogLevel INFO
AllowUsers ${ALLOWED_USER}
EOF

pkill sshd 2>/dev/null; sshd

Two corrections vs. the older guides: ChallengeResponseAuthentication was deprecated in OpenSSH 8.4 and replaced by KbdInteractiveAuthentication — use the new name. And a single-quoted heredoc ('EOF') would have written the literal string $(whoami) into your config and locked you out. The unquoted form above expands it for real.

Copy Your Public Key

bash
# From your laptop — ssh-copy-id ships inside Termux's openssh package
ssh-copy-id -p 8022 -i ~/.ssh/id_ed25519.pub u0_a123@192.168.1.50

# Manual equivalent:
# scp -P 8022 ~/.ssh/id_ed25519.pub u0_a123@192.168.1.50:~/.ssh/authorized_keys

⚠ Running sshd means your LAN can reach your phone — and your phone has no firewall you control. Key-only auth is the floor, not the ceiling: never port-forward 8022 to the internet (use WireGuard for remote access), and consider binding ListenAddress to your WiFi IP instead of listening on every interface.

Bonus: Kill the Animations (ADB, No Root)

Cosmetic, but the phone feels faster and it costs nothing:

adb
# From your PC with USB debugging enabled — no root required
adb shell settings put global window_animation_scale 0.5
adb shell settings put global transition_animation_scale 0.5
adb shell settings put global animator_duration_scale 0.5

⚠ Needs USB debugging (adb) or root. Purely cosmetic — skip it if you can't be bothered.

Gotchas & Rabbit Holes

"Permission denied" on Storage Writes

Cause: Android 11+ scoped storage. Fix: use ~/storage/shared/Download, never hardcoded /sdcard/.... Revoked the permission? Re-run termux-setup-storage.

proot-distro Fails to Start a Session

Cause: kernel too old for the image's syscalls, or a session that refuses to come up under heavy bindings. Fix: drop to the bare session — proot-distro login ubuntu --minimal — or install a featherweight image: proot-distro install alpine. The old ubuntu-minimal / --variant minimal incantations from older guides no longer exist in v5.x.

SSH Connection Refused / Timeout

  1. pgrep sshd — is it even running?
  2. ss -tln | grep 8022 — listening?
  3. Battery optimization killed it — check "Unrestricted" again.
  4. Router/AP client isolation blocking LAN traffic — phone can't reach your PC either.
  5. Debug with sshd -d in the foreground and read the config errors.

Python / Node Native Modules Fail to Compile

termux
# Toolchain first — build-essential covers clang, make, pkg-config
pkg install -y build-essential
# numpy/pandas: the BLAS backends make a real difference
pkg install -y libopenblas liblapack
# node native modules: headers ship with nodejs itself
pkg install -y nodejs python3 make clang

Termux Killed in Background on Android 12+

Android 12+ caps "phantom" processes at 32 per app and kills anything burning excessive CPU. Symptoms: [Process completed (signal 9)] out of nowhere. Battery exemption + termux-wake-lock helps; for heavy jobs, run them inside a distro or in chunks.

Termux Crashes on Startup

termux
# A bad .bashrc can brick your interactive session — rename and restart
mv ~/.bashrc ~/.bashrc.bak

# Prefer a clean reset over a full reinstall
termux-reset    # restores default configs, keeps packages and $HOME

Out of Memory / Killed Processes

Non-root fixes only — no swap tricks here:

  1. Close background Android apps (real RAM).
  2. Lighter distro: proot-distro install alpine, then --minimal.
  3. htop and find the leak instead of fighting the symptom.

Takeaways

  • One source, all apps — F-Droid or GitHub, never both. Every Termux app shares a signing key and sharedUserId; mixing sources quietly breaks plugins and forces a wipe.
  • The kernel's rules still apply — non-root Termux cannot create swap or reconfigure ZRAM; Android manages it. Check /proc/swaps, then spend your effort on footprint (alpine, --minimal) instead of fake RAM.
  • proot-distro is an OCI tool nowinstall kalilinux/kali-rolling (not kali), Kali ships zero tools by default, pin ubuntu:24.04, and use --shared-tmp / --minimal to control the session.
  • Battery exemption + wake lock + Termux:Boot = a server that stays up — Android will kill sshd within minutes without all three. And harden it: key-only, port 8022, config at $PREFIX/etc/ssh/sshd_config, never forward to the internet.

Anchor Insight

Termux isn't a "Linux simulator" — it's a real Linux userspace on the kernel your phone already runs. Non-root doesn't mean "can't do much"; it means the kernel's rules apply to you exactly as they do to any unprivileged user. Learn where root is genuinely required (swap, ZRAM, /sys writes) and where it isn't (packages, containers, SSH, storage) — and a $200 phone becomes a serious lab.


Related Articles (Internal Linking)


Last verified: August 14, 2026 | Termux v0.118.3 stable (0.119.0-beta on F-Droid) | proot-distro v5.6.0 | Android 7.0–16 tested