InfrastructureGuide

Extract an Ubuntu rootfs into Termux proot by hand

When proot-distro install fails on an old Termux: download the Ubuntu 25.10 armhf rootfs tarball and extract it into the proot directory yourself.

Context

PocketClaw initially ran inside a proot Ubuntu environment because Termux's native Node.js (v12) was too old for OpenClaw. The plan was to install Ubuntu via proot-distro install ubuntu, but on the Moto E2's old Termux (apt-android-5 variant, v0.119.0-beta.3), the install script failed with checksum mismatches and download errors.

The proot-distro tool expects a specific tarball format and SHA256 hash that changes between releases. When the tool's metadata is outdated, it downloads the wrong file or fails validation. Rather than trying to update proot-distro itself (which would require a newer Termux), the rootfs can be extracted manually.

This hack is now LEGACY: the native gateway migration (Hack #12) eliminated the need for proot entirely. Documented for reference and recovery scenarios.

Prerequisites

  • Termux with proot installed (pkg install proot)
  • proot-distro package installed (for the login command)
  • Internet connection for downloading the rootfs

Implementation

Download the Ubuntu armhf rootfs tarball directly from Ubuntu's CDN and extract it into the proot directory structure that proot-distro login ubuntu expects:

# Create the rootfs directory
ROOTFS=$PREFIX/var/lib/proot-distro/installed-rootfs/ubuntu
mkdir -p $ROOTFS

# Download Ubuntu 25.10 armhf base rootfs
curl -sL -o /tmp/ubuntu.tar.gz \
  "https://cdimage.ubuntu.com/ubuntu-base/releases/25.10/release/ubuntu-base-25.10-base-armhf.tar.gz"

# Extract into rootfs directory
cd $ROOTFS && tar xf /tmp/ubuntu.tar.gz

# Configure DNS (proot doesn't inherit resolv.conf)
echo "nameserver 8.8.8.8" > $ROOTFS/etc/resolv.conf
echo "nameserver 8.8.4.4" >> $ROOTFS/etc/resolv.conf

# Clean up the downloaded tarball
rm /tmp/ubuntu.tar.gz

After extraction, enter the proot environment:

# Login to the Ubuntu proot
proot-distro login ubuntu

# Inside proot - update packages
apt update && apt upgrade -y

# Install essential tools
apt install -y curl wget ca-certificates

Verification

# Check rootfs exists and has content:
ls $PREFIX/var/lib/proot-distro/installed-rootfs/ubuntu/bin/
# Expected: bash, ls, cat, etc.

# Test proot login:
proot-distro login ubuntu -- cat /etc/os-release
# Expected: VERSION="25.10 (Quantal Quetzal)" or similar

# Test DNS resolution inside proot:
proot-distro login ubuntu -- ping -c 1 google.com
# Expected: response from google.com

Gotchas

  • The rootfs URL changes with each Ubuntu release. Check cdimage.ubuntu.com for the current armhf base tarball
  • The rootfs takes ~967 MB on disk. On the Moto E2 with 4 GB internal storage, this is significant
  • proot adds ~15% CPU overhead and ~8 MB RAM overhead per process
  • File I/O inside proot is ~30% slower due to path translation
  • This approach is now superseded by the native Node.js build (Hack #12) which eliminates proot entirely

Result

MetricBeforeAfter
proot-distro installFailsN/A (manual)
Ubuntu rootfsMissingWorking
Disk usage0~967 MB
Node.js availablev12 (Termux)v22 (inside proot)