Wednesday, October 1, 2025

Ubuntu Server on QEMU emulator

1. Download an Ubuntu server cloud qcow2 disk image.

wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img

2. Create cloud-init configuration files

Also, you can generate an SSH key pair and use it to login over SSH if you put the public key as I did below. cloud-init will automatically write it to ~/.ssh/authorized_keys
touch meta-data
touch network-data
touch vendor-data

cat << EOF > user-data
#cloud-config
users:
  - name: ubuntu
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: sudo
    shell: /bin/bash
    lock_passwd: false
    password: password
    ssh_authorized_keys:
      - <your public SSH key>

chpasswd:
  list: |
    ubuntu:password
  expire: False

ssh_pwauth: True
EOF

3. Create an ISO disk image out of those files

The volume id should be cidata.

xorriso -as mkisofs \
    -output seed.img \
    -volid cidata -rational-rock -joliet \
    user-data meta-data network-config

4. Run the guest OS

Notice that the disk image that holds Ubuntu Server and the CD-ROM disk image are both "plugged in" to the machine being emulated.

qemu-system-x86_64 \
  -m 2G \
  -accel tcg \
  -drive file=noble-server-cloudimg-amd64.img,if=virtio,format=qcow2 \
  -drive file=seed.img,format=raw,media=cdrom \
  -netdev user,id=net0 \
  -device virtio-net-pci,netdev=net0,hostfwd=tcp::2222-:22 \ # you only need hostfwd if you're using ssh
  -nographic

Now, in the guest OS:

ubuntu@ubuntu:~$ uname -a
Linux ubuntu 6.8.0-90-generic #91-Ubuntu SMP PREEMPT_DYNAMIC Tue Nov 18 14:14:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

In this case, the username is ubuntu, and the password is password. If you set up SSH, you can login without your password:

ssh -p 2222 -i private_key ubuntu@localhost

5.  Optionally, mount the host file-system onto guest's file system

Make sure that QEMU is compiled with support for the 9p protocol. Add this to the QEMU invocation:
-virtfs local,path=/Users/varunnawathey,mount_tag=share0,security_model=passthrough
And, in the guest, mount the file system tag
sudo mount -t 9p share0 /mnt

Relevant Documentation: