Running redroid (Android in a Docker container) on a plain ARM64 cloud server. Empty Ubuntu box to a working Android instance answering ADB: under 30 minutes, about €0.60 of server time.
Most redroid guides online still document the pre-binderfs way of setting up the kernel side. On any current kernel that produces a container which starts, sits there, and dies with nothing useful in the logs. This repo is the version that works on kernel 6.x, with the dead ends written down.
Tested 2026-08-28 on Scaleway BASIC2-A2C-4G (Ampere ARM64, 2 vCPU, 4 GB), Ubuntu 24.04, kernel 6.8.0-106-generic, PAR1. Connected over ADB from a laptop in Hanoi to a server in Paris.
# 1. Check the environment BEFORE installing anything
uname -m # aarch64
getconf PAGESIZE # 4096 <-- this is the gate
uname -r # 6.8.0-106-generic
# 2. binder
apt update
apt install -y linux-modules-extra-$(uname -r)
modprobe binder_linux devices="binder,hwbinder,vndbinder"
# 3. binderfs — the step almost every guide is missing
mkdir -p /dev/binderfs
mount -t binder binder /dev/binderfs
ls /dev/binderfs # binder-control, binder, hwbinder, vndbinder
# 4. Docker
curl -fsSL https://get.docker.com | sh
# 5. Run it (ADB bound to localhost only — see Security)
mkdir -p /root/redroid-data
docker run -itd --privileged --name redroid13 \
-v /root/redroid-data:/data \
-p 127.0.0.1:5555:5555 \
redroid/redroid:13.0.0_64only-latestgetconf PAGESIZEMust be 4096. redroid requires 4 KB memory pages.
Oracle Linux on Ampere now defaults to 64 KB pages, and redroid fails there
with mprotect errors that look like a redroid bug and are not one. Ubuntu on
ARM64 uses 4 KB.
Run this check first. It takes one second and saves hours.
Android's IPC needs the binder_linux kernel module. On a fresh Ubuntu 24.04
ARM image it isn't present:
apt install -y linux-modules-extra-$(uname -r)
modprobe binder_linux devices="binder,hwbinder,vndbinder"modprobe succeeds. And then /dev/binder, /dev/hwbinder and
/dev/vndbinder do not exist.
That is where most people stop, because every older guide says those device
nodes should now be there. On kernel 6.x they never are. Binder moved to a
filesystem — binderfs — and the devices= module parameter is accepted but
creates nothing on its own. You have to mount it:
mkdir -p /dev/binderfs
mount -t binder binder /dev/binderfs
ls /dev/binderfs
# binder binder-control hwbinder vndbinderOne-line diagnostic that identifies this instantly:
grep binder /proc/filesystems
# nodev binder <-- binderfs kernel, mount itA lot of guides tell you to load ashmem_linux. On kernel 5.18+ with Android
12+ images this is obsolete — those images use memfd instead. Chasing
ashmem_linux on a modern system is wasted time.
None of the above survives a reboot unless you write it down:
echo binder_linux > /etc/modules-load.d/redroid.conf
echo 'options binder_linux devices=binder,hwbinder,vndbinder' > /etc/modprobe.d/redroid.conf
echo 'binder /dev/binderfs binder defaults 0 0' >> /etc/fstabThis matters more than anything else here.
ADB on port 5555 has no authentication at all. Published as
-p 5555:5555, it is open to the whole internet and anyone who finds it has
full control of the Android instance — install, read files, run shell.
Bind it to localhost and reach it through an SSH tunnel instead:
docker run ... -p 127.0.0.1:5555:5555 ...From your own machine:
ssh -i <your-key> -L 5555:127.0.0.1:5555 root@SERVER
# then, in another terminal:
adb connect 127.0.0.1:5555
adb devices
adb shell getprop ro.product.cpu.abi # arm64-v8aOne idle Android 13 instance:
| metric | value |
|---|---|
| RAM | 594 MiB |
| CPU | 0.07% |
| processes | ~1005 |
So roughly five instances fit in 4 GB. Measure with docker stats.
Hetzner CAX (ARM) is the cheapest at about €0.011/hour. On the day of this test its ARM stock was sold out in every location — Helsinki, Falkenstein and Nuremberg all unavailable. Scaleway had capacity immediately at €0.0293/hour.
If you are recommending a provider for ARM workloads, mention availability, not just the hourly price.
docker logs -f redroid13
adb shell getprop sys.boot_completed # 1
adb shell getprop ro.product.cpu.abi # arm64-v8a (native ARM, no translation)docker rm -f redroid13Then delete the server in your provider's console so billing stops. Hourly billing does not stop when the container does.
I needed to answer a client honestly about whether redroid runs on ARM64 cloud servers and what it costs, so I ran it instead of guessing. These are the notes from that run, including the things that went wrong.
Corrections and additions welcome — open an issue.
— Bill · fullstacksolutiondev.com