Operations 14 min read

Build a Lightweight Ubuntu VM on macOS with Virtualization Kit and vftool

This guide walks through using macOS Big Sur's Virtualization Kit together with the open‑source vftool to compile, sign, and run a minimal Ubuntu virtual machine, covering image preparation, network configuration, launchctl auto‑start, and essential post‑creation tweaks.

Programmer DD
Programmer DD
Programmer DD
Build a Lightweight Ubuntu VM on macOS with Virtualization Kit and vftool

This article explains how to use macOS Big Sur's Virtualization Kit and the open‑source vftool to create and manage a lightweight Ubuntu virtual machine.

1. Compile vftool

vftool is written in Swift, so you need the Xcode command‑line tools. Install them with: $ xcode-select --install Or download Xcode from the Apple developer site.

After installing the tools, clone and compile the repository:

$ git clone https://github.com/evansm7/vftool.git
$ clang -framework Foundation -framework Virtualization vftool/vftool/main.m -o /usr/local/bin/vftool

If you encounter the error "Virtualization requires the \"com.apple.security.virtualization\" entitlement", you must create a self‑signed code‑signing certificate in Keychain Access → Certificate Assistant → Create a Certificate, choose "Code Signing" as the type, and give it any name.

Sign the compiled binary with the new certificate:

$ codesign --entitlements vftool/vftool/vftool.entitlements -s "<NAME ON CERTIFICATE>" /usr/local/bin/vftool

Alternatively, you can build with Xcode directly:

$ xcodebuild
$ cp build/Release/vftool /usr/local/bin/vftool

2. Prepare image files

Download the kernel, initrd and disk image for Ubuntu 20.04:

kernel: https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic

initrd: https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-initrd-generic

disk image: https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.tar.gz

Download and rename them:

$ mkdir -p ~/bin/vm
$ cd ~/bin/vm
$ wget https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic
$ wget https://cloud-images.ubuntu.com/releases/focal/release/unpacked/ubuntu-20.04-server-cloudimg-amd64-initrd-generic
$ wget https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.tar.gz
$ mv ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic vmlinux
$ mv ubuntu-20.04-server-cloudimg-amd64-initrd-generic initrd
$ tar xvfz ubuntu-20.04-server-cloudimg-amd64.tar.gz

Create a data disk:

$ dd if=/dev/zero of=data.img bs=1m count=51200

3. Adjust VM network (optional)

To change the VM's network subnet, edit

/Library/Preferences/SystemConfiguration/com.apple.vmnet.plist

and modify the Shared_Net_Address and Shared_Net_Mask keys, e.g.:

<key>Shared_Net_Address</key>
<string>192.168.64.1</string>
<key>Shared_Net_Mask</key>
<string>255.255.255.0</string>

4. Create the virtual machine

Run vftool with the prepared files:

$ vftool \
  -k vmlinux \
  -i initrd \
  -c focal-server-cloudimg-amd64.img \
  -d data.img \
  -m 2048 \
  -a "console=hvc0"

The tool will start the VM and attach a TTY (e.g., /dev/ttys000). Open another terminal and connect to the TTY: $ screen /dev/ttys000 Inside the VM, perform initial configuration:

# touch /etc/cloud/cloud-init.disabled
# echo 'root:root' | chpasswd
# echo "podman" > /etc/hostname
# ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
# ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa
# ssh-keygen -f /etc/ssh/ssh_host_ed25519_key -N '' -t ed25519
# cat <<EOF > /etc/netplan/01-dhcp.yaml
network:
  renderer: networkd
  ethernets:
    enp0s1:
      dhcp4: no
      addresses: [192.168.64.2/24]
      gateway4: 192.168.64.1
      nameservers:
        addresses: [114.114.114.114]
  version: 2
EOF
# echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
# sed -i "/^PasswordAuthentication/ c PasswordAuthentication yes" /etc/ssh/sshd_config
# exit

After exiting, the VM can be stopped with CTRL‑C. Restart it with the same command, adding the root device if needed:

$ vftool \
  -k vmlinux \
  -i initrd \
  -d data.img \
  -m 2048 \
  -a "console=hvc0 root=/dev/vda" \
  -t 0

5. Set up automatic start with launchctl

Create a launchd plist in ~/Library/LaunchAgents (e.g., vftool.ubuntu.plist) that runs a start script:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>ubuntu</string>
    <key>ProgramArguments</key>
    <array>
      <string>/bin/bash</string>
      <string>-c</string>
      <string>$HOME/bin/vm/start.sh</string>
    </array>
    <key>StandardOutPath</key>
    <string>/var/log/vftool.ubuntu.stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/vftool.ubuntu.stderr.log</string>
    <key>KeepAlive</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
  </dict>
</plist>

Create the start script ( start.sh) that invokes vftool:

#!/bin/bash
$HOME/bin/vftool \
  -k $HOME/bin/vm/vmlinux \
  -i $HOME/bin/vm/initrd \
  -d $HOME/bin/vm/data.img \
  -m 2048 \
  -a "console=hvc0 root=/dev/vda" \
  -t 0

Make the script executable and create log files with write permission:

$ chmod +x start.sh
$ touch /var/log/vftool.ubuntu.stdout.log
$ touch /var/log/vftool.ubuntu.stderr.log
$ sudo chmod a+rw /var/log/vftool.ubuntu.stdout.log
$ sudo chmod a+rw /var/log/vftool.ubuntu.stderr.log

Load and start the service:

$ launchctl load -w ~/Library/LaunchAgents/vftool.ubuntu.plist
$ launchctl start ubuntu

Verify the service: $ launchctl list ubuntu Now the Ubuntu VM starts automatically on macOS boot and can be accessed via SSH: $ ssh [email protected] References:

Apple Virtualization Kit documentation

vftool GitHub repository

Ubuntu cloud image URLs

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

vmVirtualizationUbuntuvftool
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.