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=passthroughsudo mount -t 9p share0 /mnt