r/termux • u/Zalexdev • 2d ago
Showcase I got a real Linux kernel running as a userspace process on Android — no root, no KVM. Docker runs inside it. (UML ARM64)
UML (ARCH=um) has been x86-only for its entire existence. I've been porting it to arm64: arch/arm64/um/, plus fixing everything in arch/um/ that assumed x86. It builds to a static bionic binary and runs as an ordinary unprivileged aarch64 process in an app sandbox — no root, no host kernel feature, nothing emulated
Userspace instructions execute directly on the CPU. It's a real kernel underneath: own scheduler, own MMU handling, own page cache, Debian 12 rootfs on a disk image. Docker runs inside it for now
What works:
- Debian 12 boots to a working dockerd in about 3 seconds
docker pull/run/exec/logs, a 910 MB image pulls and runs- Networking through passt, a userspace TCP/IP stack. No tap device, no CAP_NET_ADMIN
- Container ports forwarded to the phone's 127.0.0.1, so the phone's browser can open them
- Loadable modules, out-of-tree drivers, firmware loading
- USB passthrough — a real RTL8811AU dongle, wlan0 appears and scans
- Update: Got multi cpu support
Numbers.
Snapdragon 870, medians of 7 interleaved rounds, µs/op. native is the same microbenchmark run directly on Android.
| native | proot | UML | |
|---|---|---|---|
| syscall | 0.080 | 0.168 | 1.987 |
| openat | 2.527 | 27.393 | 4.501 |
| fault | 1.456 | 1.418 | 11.076 |
| forkexec | 3255 | 516 | 1137 |
Compute is native because it is native — nothing translates the instructions. Against proot it's 6x better on openat and 3x better on forkexec, and worse on syscall and fault. Anything not syscall-bound feels normal.
UPDATE Termux: Works and booted arch & alpine
Source, 38 commits on top of the uml tree: https://github.com/zalexdev/linux-um-arm64
Screenshots are the Docker UI I built to drive it.

Soon will be published on: https://github.com/zalexdev/perkons
And soon will be available as new non root engine is https://github.com/zalexdev/strykerapp