For years, iOS developers and security researchers faced a frustrating choice. You either bought a stack of physical iPhones and plugged them into a USB hub, or you relied on the Xcode Simulator. The simulator works well for basic UI testing, though it is not a real iOS system. It is a macOS process compiling your code for a simulated target. It shares the host kernel, lacks true sandboxing constraints, and fails to mimic actual device hardware.
If you needed to test kernel-level changes, audit security configurations, or run automated testing pipelines on native ARM64 iOS builds, you were out of luck.
Apple Silicon changed this. With the introduction of M-series chips, the hardware gap between Macs and iOS devices closed. Apple introduced Virtualization.framework, a low-level API that allows macOS to run guest operating systems with native hardware acceleration. While most developers use this to run macOS or Linux virtual machines, the framework also supports booting virtualized iOS and iPadOS environments. By using command-line utilities like vphone-cli, you can spin up and configure virtual iPhones directly on your Mac.
The Architecture: Simulator vs. Native Virtualization
To understand why virtualization matters, we must look at how the guest system interacts with the host hardware. The Xcode Simulator uses a translation layer. When you run an app in the simulator, Xcode compiles the app using the simulator SDK. The binary runs directly on the macOS kernel, using macOS system libraries modified to look like iOS. This means security policies, memory management, and kernel behaviors are those of macOS, not iOS.
Virtualization is different. Apple Virtualization.framework interacts directly with the Apple Silicon hypervisor. It boots a complete guest operating system, including its own kernel, system daemons, and security policies. The guest OS runs in its own isolated memory space.
When you boot an iOS guest image (delivered as an IPSW file), the hypervisor manages the execution of guest instructions. Because both the host Mac and the target iOS device run on ARM64 architecture, there is no need for slow instruction translation. The guest OS runs instructions directly on the physical CPU cores. Virtualization.framework exposes virtual devices to the guest, including virtual disks and network interfaces.
This architecture makes virtualized iOS instances a valuable addition to your developer-tools suite. You get a sandboxed environment that behaves exactly like physical hardware, without the overhead of physical cables or battery management.
Getting Started with vphone-cli
While Apple provides the APIs in Virtualization.framework, writing a custom Swift application to configure and boot a virtual machine requires significant boilerplate. You have to define the hardware model and boot loader configuration manually.
To bypass this manual setup, developers use vphone-cli. This command-line tool wraps the Virtualization.framework APIs, allowing you to manage virtual iOS devices using simple terminal commands.
Before setting up your first virtual iPhone, ensure your host machine meets the requirements. You need an Apple Silicon Mac running macOS Ventura (13.0) or later. Xcode Command Line Tools must be installed. You can install them by running:
xcode-select -installOnce the command line tools are ready, you can install vphone-cli by cloning the repository and compiling it. Building from source ensures you have the latest updates for iOS virtualization.
git clone https://github.com/example/vphone-cli.git
cd vphone-cli
make build
sudo make installVerify the installation by running the version command. This command should return the version number and confirm that the tool can communicate with the hypervisor.
vphone-cli -versionDownloading the IPSW Image
A virtual iPhone requires an operating system image to boot. Apple distributes iOS and iPadOS updates as IPSW files. Because of Apple's signing requirements, you must use an IPSW version that Apple is currently signing. For virtual environments, we use the iPadOS IPSW, as Apple configures iPadOS images to boot on Apple Silicon virtualization hosts.
You can find IPSW download links on sites like ipsw.me or directly from the Apple Developer portal. Download the image for the target device profile that matches your host architecture. Save the file to a dedicated directory:
mkdir -p ~/vms/ios-images
mv ~/Downloads/iPad_17.5_Restore.ipsw ~/vms/ios-images/Using a dedicated directory helps keep your virtual machine assets organized, especially when managing multiple OS versions for compatibility testing.
Initializing the Virtual Machine
With the IPSW file downloaded, you can initialize the virtual device. The initialization process creates the virtual hardware configuration, allocates disk space, and configures the auxiliary storage.
Run the initialization command:
vphone-cli init -name "ios-test-device" -ipsw ~/vms/ios-images/iPad_17.5_Restore.ipsw -disk-size 32GBThis command performs several actions behind the scenes:
- It extracts the hardware model and restore information from the IPSW.
- It creates a virtual disk image of 32 gigabytes to serve as the guest system's storage.
- It generates an auxiliary storage file to hold the NVRAM variables and boot state.
- It writes a configuration file containing the CPU core allocation, memory limits, and display resolution.
You can inspect the generated configuration file. It looks similar to this:
{
"name": "ios-test-device",
"cpu_count": 4,
"memory_size_mb": 4096,
"display": {
"width": 1920,
"height": 1080,
"pixels_per_inch": 264
},
"disk_path": "./disk.img",
"aux_path": "./aux.bin"
}You can modify these values manually. For example, if you are running on a Mac Studio with plenty of resources, you can increase the CPU count to 6 and the memory to 8192 megabytes to speed up application testing.
Installing the Guest OS
Before you can boot the virtual device, you must install the OS from the IPSW onto the virtual disk. This step matches the recovery restore process on a physical device.
Run the install command:
vphone-cli install -config ~/vms/ios-test-device/config.jsonThe installation process takes a few minutes. vphone-cli mounts the IPSW, copies the system files, and configures the recovery partition. A progress bar in the terminal shows the status. Once complete, you will see a success message indicating the virtual machine is ready for its first boot.
Booting the Virtual Device
To start the virtual iPhone, run the start command:
vphone-cli start -config ~/vms/ios-test-device/config.jsonA graphical window opens showing the Apple logo, followed by the standard setup assistant. You can use your Mac's mouse and keyboard to interact with the screen.
Because this is a clean installation, you must go through the initial setup steps: language selection and region setup. Once you complete the setup, you are presented with the home screen.
Networking and Developer Options
By default, vphone-cli configures a NAT network interface for the virtual machine. The guest OS shares the host Mac's internet connection. You can open Safari inside the virtual device to verify connectivity.
For developer-tools integration, you need to enable Developer Mode on the guest OS. Go to Settings > Privacy & Security > Developer Mode, and toggle it on. The system will prompt you to restart the virtual machine.
After rebooting, you can connect to the virtual device using Xcode or command-line tools like cfgutil (Apple Configurator CLI). If you run xcrun devicetool list or open Xcode's Organizer, the virtual device appears as a connected network device. You can deploy apps and attach debuggers just as you would with a physical device.
Infrastructure and CI/CD Automation
One of the main benefits of virtualizing iOS is the ability to automate testing infrastructure. Running physical device farms is expensive and hard to maintain. Devices overheat and battery swelling is a constant hazard. Resetting devices to a clean state between test runs also takes time.
With vphone-cli, you can script the entire lifecycle of a test runner. A typical CI/CD pipeline script might look like this:
#!/bin/bash
# Clone the base VM
vphone-cli clone -source ~/vms/base-ios -target ~/vms/temp-runner-$GITHUB_RUN_ID
# Start the VM in headless mode
vphone-cli start -config ~/vms/temp-runner-$GITHUB_RUN_ID/config.json -headless &
# Wait for the device to boot
vphone-cli wait-for-boot -config ~/vms/temp-runner-$GITHUB_RUN_ID/config.json -timeout 120
# Run test suite
xcodebuild test -scheme "MyApp" -destination "platform=iOS,id=`(vphone-cli get-udid -config ~/vms/temp-runner-`GITHUB_RUN_ID/config.json)"
# Stop and destroy the VM
vphone-cli stop -config ~/vms/temp-runner-$GITHUB_RUN_ID/config.json
vphone-cli destroy -config ~/vms/temp-runner-$GITHUB_RUN_ID/config.jsonThis approach ensures every test run starts on a clean operating system image, eliminating state leakage between test runs. You can scale the number of concurrent runners based on the host Mac's hardware resources. Teams can build out virtualized infrastructure that runs locally or on bare-metal cloud instances of Apple Silicon.
Security Auditing and Kernel Research
For security teams, virtualized iOS environments are highly useful. Analyzing malware or reverse-engineering applications on physical hardware is difficult because Apple's security systems restrict access to the underlying kernel.
While virtualization does not bypass security features like System Integrity Protection (SIP) or Kernel Patch Protection (KPP) inside the guest by default, it does give you control over the execution environment. You can attach debuggers to the hypervisor layer or monitor guest physical memory access from the host.
Because the guest disk is a simple image file on the host, you can mount the filesystem on macOS to inspect application sandboxes and database files without needing to jailbreak the guest device. If a malware sample crashes the system or modifies system files, you can restore the system to a clean snapshot in seconds.
Current Limitations
Despite the benefits of Virtualization.framework, there are several limitations to keep in mind:
- Apple Account Integration: You cannot log into iCloud or use Apple Services (like the App Store or iMessage) on a virtual iOS device. Apple's servers block authentication requests from virtualized hardware identifiers. Apps that rely on CloudKit or Apple Sign-In will fail or require mock interfaces.
- GPU Acceleration: While macOS guests enjoy full metal GPU acceleration, iOS guest support is still limited. UI rendering works fine, but graphics-heavy apps or games may experience lag or rendering bugs.
- Hardware Passthrough: There is no direct way to pass through host USB devices, cameras, or Bluetooth adapters to the guest OS. If your app relies on physical sensors, you must mock those inputs.
Virtualizing iOS on Apple Silicon using Virtualization.framework and vphone-cli bridges the gap between the limited Xcode Simulator and expensive physical device farms. It allows developers to run native ARM64 builds in isolated environments, automate testing pipelines, and conduct security audits. As Apple continues to update its virtualization APIs, the parity between physical and virtual test environments will only improve.



