< Back to all hacks

#02 Ubuntu 25.10 Rootfs Manual Extraction

Infrastructure
Problem
Official proot-distro install script fails on old Termux versions.
Solution
Download Ubuntu 25.10 armhf rootfs tar.xz manually, extract into proot directory.
Lesson
When package managers fail, manual extraction of rootfs tarballs works on any Termux version.

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)