# Running Ubuntu ARM Virtual Machines on macOS with QEMU + SSH Access

When using an Apple Silicon Mac, running virtual machines can be tricky, especially when you want a full Linux environment with working networking and SSH access. Fortunately, **QEMU**, combined with macOS’s lightweight **HVF (Hypervisor Framework)** acceleration, makes this possible and surprisingly smooth.

In this guide, we will:

* Set up QEMU for ARM virtualization
    
* Create and install Ubuntu on a raw disk image
    
* Run the VM with proper hardware configs
    
* Fix SSH networking when the VM initially has no external access
    
* Successfully SSH into the VM via port forwarding
    

## Why QEMU?

QEMU isn’t just an emulator on Apple Silicon, it can use Apple’s **HVF (Hypervisor Framework)** for near-native virtualization performance.

And unlike GUI tools, QEMU gives you **full control** over networking which is important when you want SSH and cluster communication.

## **Prerequisites**

Make sure QEMU is installed:

```yaml
brew install qemu
```

This includes:

* QEMU binaries (`qemu-system-*`)
    
* Virtual device drivers
    
* UEFI firmware for ARM
    

Also download:

* **Ubuntu ARM Server ISO** (`ubuntu-24.04.3-live-server-arm64.iso`)
    
* **UEFI firmware for ARM** (QEMU\_EFI.fd) — usually packaged inside QEMU:
    

```yaml
find /opt/homebrew -name QEMU_EFI.fd
```

## Step 1: Create a Disk Image

We will create a 15GB raw disk:

```yaml
qemu-img create -f raw ubuntu-latest.raw 15G
```

This will act as your VM’s virtual hard drive.

---

## Step 2: Install Ubuntu Using QEMU

Boot with installation ISO:

```yaml
qemu-system-aarch64 \
  -monitor stdio \
  -M virt,highmem=off \
  -accel hvf \
  -cpu host \
  -smp 4 \
  -m 3000 \
  -bios /path/to/QEMU_EFI.fd \
  -device virtio-gpu-pci \
  -display default,show-cursor=on \
  -device qemu-xhci \
  -device usb-kbd \
  -device usb-tablet \
  -device intel-hda \
  -device hda-duplex \
  -drive file=ubuntu-latest.raw,format=raw,if=virtio,cache=writethrough \
  -cdrom ubuntu-24.04.3-live-server-arm64.iso
```

Then proceed through the installer normally, and **enable OpenSSH Server** when prompted.

After installation, shutdown the VM.

---

## Step 3: Start the VM (First Run)

You may try running the VM normally first:

```yaml
qemu-system-aarch64 \
  -monitor stdio \
  -M virt,highmem=off \
  -accel hvf \
  -cpu host \
  -smp 4 \
  -m 3000 \
  -bios /path/to/QEMU_EFI.fd \
  -device virtio-gpu-pci \
  -display default \
  -device qemu-xhci \
  -device usb-kbd \
  -device usb-tablet \
  -device intel-hda \
  -device hda-duplex \
  -drive file=ubuntu-latest.raw,format=raw,if=virtio,cache=writethrough
```

Inside the VM, check your IP:

```yaml
ip a
```

You'll likely see:

```yaml
10.0.2.15
```

This means NAT networking is enabled, but **SSH access from host → guest is not yet exposed**.

---

## Step 4: Add SSH Port Forwarding

We restart QEMU **with networking flags**:

```yaml
qemu-system-aarch64 \
  -monitor stdio \
  -M virt,highmem=off \
  -accel hvf \
  -cpu host \
  -smp 4 \
  -m 3000 \
  -bios /path/to/QEMU_EFI.fd \
  -drive file=ubuntu-latest.raw,format=raw,if=virtio,cache=writethrough \
  -netdev user,id=net0,hostfwd=tcp::2222-:22 \
  -device virtio-net-pci,netdev=net0
```

Now SSH should work through port **2222**:

```yaml
ssh -p 2222 username@127.0.0.1
```

But wait… sometimes it doesn’t. Instead, you may see:

```yaml
kex_exchange_identification: read: Connection reset by peer
```

This means the VM’s network interface is not configured correctly.

---

## Step 5: Fix the VM Network Interface

Inside the VM:

```yaml
ls /etc/netplan
```

You will see something like:

```yaml
50-cloud-init.yaml
```

Edit it:

```yaml
sudo nano /etc/netplan/50-cloud-init.yaml
```

Replace contents with:

```yaml
network:
  version: 2
  ethernets:
    ens3:
      dhcp4: true
```

Apply changes:

```yaml
sudo netplan apply
```

Your network now comes up correctly.

---

## Step 6: SSH Works Now!

From macOS:

```yaml
ssh -p 2222 <your-username>@127.0.0.1
```

Success!

I needed ssh to work because it was not directly possible to share the clipboard between my machine (macOS) and the Qemu VM.

---

## Summary

| Task | Command / Result |
| --- | --- |
| Create VM Disk | `qemu-img create -f raw ubuntu.raw 15G` |
| Install Ubuntu | QEMU boot with ISO |
| Run VM | QEMU run with `virtio-net-pci` |
| Fix Networking | Edit `/etc/netplan/*.yaml` and set `ens3` |
| SSH into VM | `ssh -p 2222 user@127.0.0.1` |

---

## Final Thoughts

This setup provides:

* Native-speed ARM virtualization on macOS
    
* A clean, reproducible Ubuntu VM workflow
    
* SSH access that works reliably
    
* Ready environment for Kubernetes nodes, labs, or development clusters
