How to Automate iOS VM Creation with vphone-cli: Complete Orchestration Guide
vphone-cli automates the entire iOS virtual machine provisioning workflow through a single vm create command, orchestrated by VPhoneCreateOrchestrator to execute eight distinct stages from firmware preparation to first-boot verification without manual shell scripting.
The Lakr233/vphone-cli repository provides a native Swift implementation that replaces the historic scripts/setup_machine.sh approach. By invoking the vm create subcommand defined in VPhoneVMCreateCLI.swift, developers trigger a fully-typed pipeline that downloads IPSWs, patches firmware, and restores the system using the VPhoneCreateOrchestrator class.
The vphone-cli VM Creation Architecture
The automation layer centers on two primary components. The VPhoneVMCreateCommand struct parses command-line arguments—including variant selection (regular, dev, jb, exp, or less), disk sizing, and IPSW sources—and delegates execution to the VPhoneCreateOrchestrator. This orchestrator implements the complete workflow previously distributed across multiple bash scripts, now unified within sources/vphone-cli/VPhoneCreateOrchestrator.swift.
Eight-Stage Automation Pipeline
When you execute vphone-cli vm create, the orchestrator proceeds through the following sequential stages:
1. Pre-flight Validation
Before allocating resources, the orchestrator detects nested virtualization environments. The isNestedVMHost() method (located at lines 76–82 in VPhoneCreateOrchestrator.swift) checks if the host is itself a virtual machine, aborting immediately because PV=3 guests cannot run inside another VM. This prevents wasted compute cycles on incompatible infrastructure.
2. Bundle Creation
The orchestrator initializes the VM container using VPhoneBundleOps.NewBundleSpec. During this stage, the run() method (lines 72–79) creates the bundle directory structure with specified CPU, memory, and disk parameters, establishing the virtualized hardware profile that subsequent stages will populate.
3. Firmware Preparation
This stage downloads and merges the iPhone IPSW and cloudOS IPSW archives. The runFWPrepare() function (lines 10–12) invokes the bundled scripts/fw_prepare.sh helper, passing environment variables including IPHONE_SOURCE, CLOUDOS_SOURCE, and VPHONE_PYTHON to manage the Python interpreter path and IPSW URLs. The script caches the merged result in a seal-volume directory for subsequent patching operations.
4. Firmware Patching
With the base firmware cached, runFWPatch() (lines 33–36) executes the in-process FirmwarePipeline.patchAll method from FirmwarePatcher/FirmwarePipeline.swift. This pipeline applies variant-specific modifications (regular, dev, jb, exp, or less) to the seal-volume image, preparing the custom firmware without intermediate shell calls.
5. Restore Phase
The orchestrator launches the VM in DFU mode and initiates the restore sequence via runRestorePhase() (lines 58–78). This function fetches a signed SHSH blob through the pmd3 bridge, executes the restore-update process, and records the restored iOS and cloudOS version strings. It also monitors for post-restore panic markers to detect early boot failures before proceeding.
6. Custom Firmware Installation (Non-less Variants)
For all variants except less, runCFWInstall() (lines 84–92) mounts the host disk image and copies the patched firmware into Disk.img. This stage handles privilege escalation using makeSudoAskpassScript(), which generates a non-interactive authentication helper when the --sudo-password flag is provided, enabling automated installation in CI environments.
7. First-Boot Initialization
The runFirstBoot() method (lines 100–112) boots the patched VM and injects configuration commands defined in VPhoneBootPatterns.firstBootCommands. This sequence completes system setup inside the guest, with optional interactive pauses for manual verification if the --confirm flag is specified.
8. Boot Analysis and Cleanup
Finally, runBootAnalysis() (lines 118–126) launches a headless VM instance to verify that the bash prompt appears correctly, or detects panic states using regex patterns from VPhoneBootPatterns.swift. The orchestrator then optionally removes intermediate build artifacts via cleanup logic in run() (lines 31–34) to conserve disk space.
Practical Command-Line Usage
Basic Non-Interactive Creation
Create a regular variant VM named myVM with a 64 GB virtual disk:
vphone-cli vm create myVM \
--variant regular \
--iphone-source https://example.com/iPhone13,14.5.ipsw \
--cloudos-source https://example.com/cloudOS13.7.ipsw \
--disk-size 64
Debugging with Verbose Output
Enable internal trace logging using the -vvv flag:
vphone-cli -vvv vm create myVM \
--variant jb \
--iphone-source /path/to/iPhone13.5.ipsw \
--cloudos-source /path/to/cloudOS13.3.ipsw
Patch-Less Variant (Requires Root)
The less variant skips CFW installation and must run with elevated privileges:
sudo vphone-cli vm create myVM \
--variant less \
--iphone-source /path/to/iPhone13.5.ipsw \
--cloudos-source /path/to/cloudOS13.3.ipsw
Automated Sudo Authentication
Pass credentials non-interactively for CI pipelines:
vphone-cli vm create myVM \
--variant dev \
--iphone-source https://example.com/iPhone13.5.ipsw \
--cloudos-source https://example.com/cloudOS13.3.ipsw \
--sudo-password "$MY_SUDO_PWD"
Preserving Build Artifacts
Retain intermediate files for forensic analysis:
vphone-cli vm create myVM \
--keep-artifacts \
--variant exp
Core Implementation Files
VPhoneVMCreateCLI.swift– Defines thevphone-cli vm createargument interface and option parsing.VPhoneCreateOrchestrator.swift– Implements the eight-stage pipeline includingrunFWPrepare(),runFWPatch(), andrunRestorePhase().VPhoneResources.swift– Manages cache paths for IPSW files, seal-volumes, and DEB packages; resolves the bundled Python interpreter viaVPHONE_PYTHON.VPhoneProcessRunner.swift– ProvidesProcesswrapper utilities for streaming output, privilege escalation, and foreground execution.VPhoneBootPatterns.swift– Contains regex patterns for detecting VM readiness, kernel panics, and device identity extraction.VPhoneBundleOps.swift– Handles directory creation and specification of virtual hardware resources.FirmwarePatcher/FirmwarePipeline.swift– Implements the per-variant firmware modification logic consumed byrunFWPatch().scripts/fw_prepare.sh– Bash helper for IPSW downloading and merging invoked during firmware preparation.scripts/cfw_install_host.sh– Host-mount installation script for the CFW install stage.
Summary
- Single-command automation via
vphone-cli vm createeliminates manual shell scripting. - Native Swift orchestration through
VPhoneCreateOrchestratorprovides type-safe error handling and reproducibility. - Eight-stage pipeline covers validation, firmware preparation, patching, restoration, and verification.
- Variant flexibility supports
regular,dev,jb,exp, andlessfirmware configurations. - CI/CD compatibility via
--sudo-passwordand non-interactive authentication hooks.
Frequently Asked Questions
What is the difference between the "less" variant and other variants?
The less variant skips the custom firmware installation stage entirely, requiring the user to manually manage the root filesystem, and must execute with sudo privileges. Other variants (regular, dev, jb, exp) proceed through the full pipeline including automatic CFW installation via runCFWInstall().
Can vphone-cli create VMs inside a virtual machine?
No. The isNestedVMHost() function explicitly detects when the host environment is itself a virtual machine and aborts the creation process because the virtualization architecture (PV=3) used for these iOS guests cannot operate within nested hypervisors.
How does the tool handle Python dependencies for firmware operations?
The orchestrator locates the bundled Python interpreter through VPhoneResources.swift, setting the VPHONE_PYTHON environment variable when invoking scripts/fw_prepare.sh. This ensures consistent script execution regardless of system Python configurations.
Where are downloaded IPSW files cached?
The VPhoneResources module manages dedicated cache directories for IPSW archives, seal-volume images, and DEB packages within the application support directory, preventing redundant downloads across multiple VM creation runs.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →