ADR-001: Emulation Backend Selection¶
Status: Accepted
Context¶
DroidFarm runs Android virtual devices inside Kubernetes pods. The backend must: (a) run inside a container, (b) support KVM acceleration, (c) be accessible via a web browser, (d) be open-source, and (e) support Android 12+.
Three candidates were evaluated:
- budtmo/docker-android — packages Android SDK + QEMU emulator + noVNC. noVNC only (no WebRTC); QEMU overhead is heavier than Cuttlefish.
- google/android-emulator-container-scripts — official Google scripts wrapping the Android SDK emulator with a separate WebRTC frontend container. QEMU-based; requires two containers per device.
- Google Cuttlefish — Google's reference virtual Android device for AOSP testing. Uses KVM directly (not QEMU); built-in WebRTC relay on port 8443; maintained by Google at scale.
Decision¶
DroidFarm uses Google Cuttlefish as the emulation backend.
Cuttlefish uses KVM directly rather than QEMU-on-KVM, reducing per-instance memory footprint (~2–3 GB vs ~4–5 GB RAM). Its built-in WebRTC relay on port 8443 eliminates the need for a separate streaming sidecar. Non-privileged Kubernetes deployment is achieved via squat/generic-device-plugin, which exposes /dev/kvm, /dev/vhost-net, /dev/vhost-vsock, and /dev/vsock as Kubernetes resource limits. Required capabilities are NET_ADMIN, NET_RAW, and SYS_ADMIN; --privileged mode is not used.
Node setup¶
Kernel modules required on every emulator node:
This is automated via the node-setup-daemonset.yaml Helm template.
Device plugin resource requests¶
resources:
limits:
squat.ai/kvm: "1"
squat.ai/vhost: "3" # one each for vhost-net, vhost-vsock, vsock
Emulator pod security context¶
Cuttlefish container image¶
The Cuttlefish image is built by layering host tools (cvd-host_package.tar.gz) and Android system images onto a base Debian container. DroidFarm provides docker/Dockerfile.cuttlefish and a GitHub Actions matrix workflow that builds and pushes ghcr.io/christopherime/cuttlefish:{android-version} for Android 13, 14, and 15.
Ports¶
| Port | Protocol | Purpose |
|---|---|---|
| 8443 | HTTPS/WSS | Cuttlefish WebRTC relay (browser access) |
| 5554 | TCP | ADB (Android Debug Bridge) |
| 6444 | TCP | Cuttlefish operator API |
| 15550–15599 | UDP | WebRTC media (SRTP, requires TURN for NAT) |
TURN server¶
coturn is deployed as a Helm component for WebRTC across NAT. TURN credentials are stored in a Kubernetes Secret and never appear in values files or process arguments.
Consequences¶
- Cuttlefish images must be built and published per Android version (handled by CI).
- Image size is larger than docker-android due to Android system disk images (~3–8 GB per version).
- WebRTC streaming works from first deploy — no intermediate noVNC phase.
- coturn is a required component for non-LAN WebRTC access; TURN bandwidth must be budgeted per concurrent session.