Skip to content

Setup Cuttlefish

This guide prepares a Linux host to run Android Automotive virtual devices with Cuttlefish. Use this path when you want a fast validation target without flashing physical MEK or NeuralPlex hardware.

The intended workflow is:

  1. Build or retrieve a Cuttlefish-compatible image on the build server.
  2. Launch the virtual device on the server.
  3. Access the device from your laptop with adb and, when needed, the browser-based WebRTC UI.

Use an Ubuntu host with:

  • Ubuntu 24.04
  • x86_64 CPU with hardware virtualization support
  • /dev/kvm available to the user running Cuttlefish
  • the user in the kvm, cvdnetwork, and render groups
  • at least 50 GB free for one extracted image, host package, runtime state, and logs; 100 GB or more is better if the host keeps multiple images

To check the basics:

Terminal window
grep -c -w 'vmx\|svm' /proc/cpuinfo
ls -l /dev/kvm
ls -l /dev/dri/renderD*
id -nG
df -h /srv/android-automotive

If /dev/kvm is missing or the CPU virtualization count is 0, fix host virtualization before continuing.

Cuttlefish host tools are distributed as Ubuntu packages, but they are not in Ubuntu’s default package repositories. Register Google’s Android Cuttlefish Artifact Registry repository first:

Terminal window
sudo apt update
sudo apt install -y curl ca-certificates
sudo curl -fsSL https://us-apt.pkg.dev/doc/repo-signing-key.gpg \
-o /etc/apt/trusted.gpg.d/artifact-registry.asc
sudo chmod a+r /etc/apt/trusted.gpg.d/artifact-registry.asc
echo "deb https://us-apt.pkg.dev/projects/android-cuttlefish-artifacts android-cuttlefish main" \
| sudo tee /etc/apt/sources.list.d/android-cuttlefish-artifacts.list
sudo apt update

Install the base runtime and the user-facing browser interaction service:

Terminal window
sudo apt install -y \
cuttlefish-base \
cuttlefish-user

The package setup should create the cvdnetwork group. Add the build user to the required groups:

Terminal window
sudo usermod -aG kvm,cvdnetwork,render "$USER"

Log out and back in, or reboot the host, before launching a device. Confirm the new groups are present with:

Terminal window
id -nG

Before using repo-built artifacts, validate the host with a known-good Cuttlefish image and matching host package.

Download both artifacts from the same Android CI build. This known-good image is only for validating the host setup, so use the standard Cuttlefish Android Automotive target first.

Build 15660610 is a known-good aosp_cf_x86_64_auto-userdebug build for this smoke test.

The host package and image zip must come from the same build. Mixing versions can produce launch failures that look like host setup problems.

The Android CI artifact pages are viewer pages. Downloading those URLs directly with curl saves the viewer HTML, not the artifact. Extract the signed artifact URL from the viewer page, then download that signed URL:

Terminal window
download_ci_artifact() {
viewer_url="$1"
output_path="$2"
signed_url="$(curl -fsSL "$viewer_url" \
| sed -n 's/.*"artifactUrl":"\([^"]*\)".*/\1/p' \
| sed 's/\\u0026/\&/g')"
test -n "$signed_url"
curl -L "$signed_url" -o "$output_path"
}
download_ci_artifact \
"https://ci.android.com/builds/submitted/15660610/aosp_cf_x86_64_auto-userdebug/latest/cvd-host_package.tar.gz" \
/tmp/cvd-host_package.tar.gz
download_ci_artifact \
"https://ci.android.com/builds/submitted/15660610/aosp_cf_x86_64_auto-userdebug/latest/aosp_cf_x86_64_auto-img-15660610.zip" \
/tmp/aosp_cf_x86_64_auto-img.zip

Create a clean working directory:

Terminal window
mkdir -p /srv/android-automotive/cuttlefish
cd /srv/android-automotive/cuttlefish

Extract the host package and image artifacts from the same Android build:

Terminal window
file /tmp/cvd-host_package.tar.gz /tmp/aosp_cf_x86_64_auto-img.zip
tar -xvf /tmp/cvd-host_package.tar.gz
unzip /tmp/aosp_cf_x86_64_auto-img.zip

If file reports HTML or JavaScript instead of gzip and zip archives, the download saved the Android CI artifact viewer page. Re-run the download helper from the previous section.

Launch the device:

Terminal window
HOME="$PWD" ./bin/launch_cvd --daemon

Confirm the host package’s adb sees the device:

Terminal window
./bin/adb devices
./bin/adb shell getprop ro.build.fingerprint

After the host works with the known-good upstream image, build the repo’s MRS Cuttlefish target on the build server:

Terminal window
cd /srv/android-automotive
just build cuttlefish

When the build finishes, the runnable artifacts are published in:

/srv/android-automotive/releases/imx-automotive-16.0.0_1.1.0/cuttlefish/

From your laptop, pull those artifacts into the repo workspace:

Terminal window
just pull-build-artifacts user@host cuttlefish

To run them on the Cuttlefish host, launch the published artifacts:

Terminal window
cd /srv/android-automotive
just launch-cuttlefish

The launch recipe stops any existing instance in /srv/android-automotive/cuttlefish-mrs, recreates that runtime directory, extracts cvd-host_package.tar.gz and the newest *-img-*.zip from the published Cuttlefish artifacts, then starts launch_cvd --daemon with HOME pointed at the runtime directory. It also enables the Cuttlefish serial console with --console=true so early boot and userspace failures can be debugged even when adb is not available.

Open the serial console with:

Terminal window
cd /srv/android-automotive
just console-cuttlefish

Only one interactive serial console session can attach at a time. The recipe uses the stable screen session name mrs-cuttlefish-console, creates it when needed, and reconnects to it if it is already detached. Use Ctrl-a d to detach without closing the guest shell.

Stop the MRS Cuttlefish instance with:

Terminal window
cd /srv/android-automotive
just stop-cuttlefish

The MRS product inherits the upstream aosp_cf_x86_64_auto Cuttlefish product and includes device/mrs/mrs-common.mk, so the image contains the MRS apps, overlays, permissions, and VHAL customizations used for Android-side validation.

For command-line testing from your laptop, use your local adb. If the Cuttlefish instance exposes an ADB TCP port on the server, open the WebRTC and ADB tunnels from the repo root on your laptop:

Terminal window
just connect-cuttlefish user@host

The exact ADB port depends on how the instance is launched. Check the launch output before hardcoding the tunnel. The recipe defaults to local WebRTC port 8443 and local ADB port 6520.

For visual access, Cuttlefish provides a browser-based WebRTC UI. The default web page is usually exposed on the host at:

https://localhost:8443

The recipe runs the SSH tunnel in the background without opening a remote shell. It is equivalent to:

Terminal window
ssh -M -S /tmp/android-os-cuttlefish-user@host-8443-6520.sock \
-o ExitOnForwardFailure=yes \
-N -f \
-L 8443:localhost:8443 \
-L 6520:localhost:6520 \
user@host

Open https://localhost:8443 in your browser. Cuttlefish does not serve this UI over plain HTTP. The browser will show an untrusted certificate warning for localhost; this is expected when accessing the WebRTC UI through a local SSH tunnel.

WebRTC also uses additional TCP and UDP ports for streaming, commonly in the 15550..15599 range. For reliable remote access, prefer a private network such as WireGuard or Tailscale, or explicitly allow those ports between your laptop and the Cuttlefish host.

When you are done, close the tunnel from the repo root:

Terminal window
just disconnect-cuttlefish user@host

Stop a running instance with:

Terminal window
HOME="$PWD" ./bin/stop_cvd

Remove the working directory only after stopping the instance.

Useful logs are in /srv/android-automotive/cuttlefish-mrs/cuttlefish/instances/cvd-1/logs/

Look at:

  • kernel.log
  • launcher.log
  • logcat
  • and others