the Chromium logo

The Chromium Projects

Running a Prebuilt ChromiumOS VM

This guide details how to download a prebuilt ChromiumOS VM image, set up the necessary environment, and run it using QEMU/KVM. While the general steps are applicable to various operating systems, this document uses Linux as an example environment.

1. Prerequisites: Install Software

Install the necessary packages on your Linux machine. This guide uses apt for Debian-based distributions like Ubuntu. If you are using a different distribution, use your respective package manager (e.g., dnf, pacman, zypper).

sudo apt update
sudo apt install -y qemu-system-x86 qemu-utils ovmf xz-utils

You also need the Google Cloud CLI to download the image. Follow the official installation instructions.

2. Set Up KVM

KVM (Kernel-based Virtual Machine) is required for hardware-accelerated emulation.

Check Hardware Support & KVM Status

if [[ -e /dev/kvm ]] && grep -qE '^flags.*(vmx|svm)' /proc/cpuinfo; then
    echo 'KVM appears to be working.'
else
    echo 'KVM not detected or not working. Ensure virtualization is' \
         'enabled in your BIOS/UEFI settings.'
fi

This checks for the KVM device and Intel (vmx) or AMD (svm) virtualization extensions.

Add User to KVM Group

sudo adduser $(whoami) kvm

Important: You may need to start a new shell session (e.g., log out and log back in, or run newgrp kvm in your current shell) for this group change to take effect.

Verify KVM Access

if [[ -r /dev/kvm ]] && [[ -w /dev/kvm ]]; then
    echo "KVM access for $(whoami) is OK."
else
    echo "KVM access for $(whoami) FAILED. Check group membership and" \
         "permissions."
fi

3. Download and Extract the Image

Set the desired ChromiumOS version (e.g., R144-16481.0.0):

export CROS_VERSION="R144-16481.0.0"

Find other versions in the Cloud Storage bucket: https://console.cloud.google.com/storage/browser/chromiumos-image-archive/amd64-generic-vm-public/

Define local directories and filenames:

export IMAGE_DIR="${HOME}/cros_vms/${CROS_VERSION}"
mkdir -p "${IMAGE_DIR}"
export ARCHIVE_FILE="${IMAGE_DIR}/chromiumos_test_image.tar.xz"
export IMAGE_FILE="${IMAGE_DIR}/chromiumos_test_image.bin"

Download the image archive using gsutil:

gsutil cp \
  "gs://chromiumos-image-archive/amd64-generic-vm-public/${CROS_VERSION}/chromiumos_test_image.tar.xz" \
  "${ARCHIVE_FILE}"

Extract the chromiumos_test_image.bin image into the versioned directory:

tar -xf "${ARCHIVE_FILE}" -C "${IMAGE_DIR}/"

4. Launching the VM with QEMU

This will launch the VM in the background.

qemu-system-x86_64 \
  -m 16G \
  -smp 4 \
  -enable-kvm \
  -cpu host,+ssse3,+sse4.1,+sse4.2,+aes,+pclmulqdq,+popcnt \
  -device virtio-rng-pci \
  -device virtio-scsi-pci,id=scsi \
  -device scsi-hd,drive=hd,bootindex=0 \
  -drive if=none,id=hd,file="${IMAGE_FILE}",format=raw,cache=unsafe \
  -device virtio-net,netdev=user0 \
  -netdev user,id=user0,hostfwd=tcp::2222-:22 \
  -vga virtio \
  -display gtk,show-cursor=on \
  -device usb-ehci,id=ehci \
  -device usb-tablet \
  -device virtio-keyboard-pci

5. Signing Into a User Session

Choose one of the following options to access the ChromiumOS user session.

This method uses the autologin.py script to log in with a fake user session, which is ideal for rapid testing.

Step 1: Auto Login and Set Chrome Flags

Connect to the VM and run the autologin script:

ssh -p 2222 -i ~/.ssh/testing_rsa \
  -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
  root@localhost \
  "/usr/local/autotest/bin/autologin.py -w -- \
    --enable-devtools-pwa-handler \
    --enable-features=IsolatedWebAppDevMode \
    --remote-debugging-address=0.0.0.0 \
    --force-devtools-available"

Wait a few seconds until the user session is ready.

Step 2: Establish a Direct Tunnel

Once logged in, you can tunnel the remote debugging port to your host machine to enable web testing. Run the following command to fetch the active port:

export HOST_PORT=9222
export ACTIVE_PORT=$(ssh -p 2222 -i ~/.ssh/testing_rsa \
  -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
  root@localhost "cat /home/chronos/DevToolsActivePort | head -n 1")

Create an SSH tunnel from your host to the VM to forward the debugging port. This terminal window must remain open during testing.

ssh -p 2222 -i ~/.ssh/testing_rsa \
    -L ${HOST_PORT}:localhost:${ACTIVE_PORT} \
    -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
    root@localhost

Verify the tunnel is working by running this command in a new terminal on your host:

curl http://localhost:${HOST_PORT}/json/version

A successful connection will return a JSON object with browser details.

Option 2: Using Real Accounts (e.g., Gmail) with API Keys

To sign into the VM with a real Google account, you need to provide Google API keys.

For SSH key authentication setup, refer to the Optional: Setup SSH Key Authentication guide.

First, you need to disable rootfs verification to be able to modify files on the system partition.

SSH into the running VM (password: test0000):

ssh -i ~/.ssh/testing_rsa -p 2222 -o StrictHostKeyChecking=no \
  root@localhost \
  '/usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification --force'

Reboot the VM:

ssh -i ~/.ssh/testing_rsa -p 2222 -o StrictHostKeyChecking=no \
  root@localhost 'reboot'

Wait for about 30 seconds for the VM to reboot.

Add Keys to the VM

To get API keys, follow the Chromium API Keys guide. It is very important to complete the step in Signing in to Chromium is restricted to be able to sign in.

Once you have your keys, remount the root filesystem as read-write:

ssh -i ~/.ssh/testing_rsa -p 2222 -o StrictHostKeyChecking=no \
  root@localhost 'mount -o remount,rw /'

Append them to /etc/chrome_dev.conf:

ssh -i ~/.ssh/testing_rsa -p 2222 -o StrictHostKeyChecking=no \
  root@localhost "echo '
GOOGLE_API_KEY=YOUR_API_KEY
GOOGLE_DEFAULT_CLIENT_ID=YOUR_CLIENT_ID.apps.googleusercontent.com
GOOGLE_DEFAULT_CLIENT_SECRET=YOUR_CLIENT_SECRET
' >> /etc/chrome_dev.conf"

And restart the UI:

ssh -i ~/.ssh/testing_rsa -p 2222 -o StrictHostKeyChecking=no \
  root@localhost 'restart ui'

After the UI restarts, you should be able to sign in with a Google account.