How to Perform IPA Installation Within a vPhone-CLI VM: Complete Technical Guide
vPhone-CLI supports IPA installation through a vsock-based pipeline that uploads the package to the guest VM, optionally applies code signing certificates, and executes the installation via the ipa_install protocol message.
Installing iOS applications into a virtual iPhone requires coordinated communication between the host and guest systems. The Lakr233/vphone-cli project provides a complete end-to-end solution for IPA installation within a vphone-cli VM, handling file transfers, validation, and sandboxed deployment without manual SSH intervention.
Architecture Overview
The installation system comprises three coordinated components working across the host-guest boundary.
User Interface Layer
The interface initiates requests through menu items or command-line flags. In VPhoneMenuApps.swift, the buildAppsMenu() function adds the "Install IPA/TIPA…" menu item, while VPhoneCLI.swift exposes the --install-ipa flag for terminal-based workflows.
Host-Side Control Layer
VPhoneControl.swift manages the actual orchestration through the installIPA(localURL:) method. This component uploads the IPA to the guest filesystem, handles optional signing certificates, and communicates with the daemon via the vsock channel.
Guest Daemon (vphoned)
Running inside the VM, the guest daemon receives ipa_install requests, validates the uploaded package, performs code signing when certificates are provided, and installs the application into the guest's sandbox.
The IPA Installation Pipeline
The complete flow from file selection to app installation follows a strict protocol designed for reliability and security.
Initiating the Install Request
Users can trigger installation through two primary paths. The interactive menu path uses installIPAFromDisk() in VPhoneMenuApps.swift, which presents an NSOpenPanel restricted to file types defined in VPhoneInstallPackage.allowedContentTypes (.ipa and .tipa).
For automation, the CLI parses the --install-ipa argument in VPhoneCLI.swift, storing the file URL and executing the installation once the control channel connects.
File Validation and Upload Preparation
Before transmission, VPhoneInstallPackage.isSupportedFile(_:) verifies the file extension. The host then prepares the transfer through VPhoneControl.installIPAWithBuiltInInstaller(localURL:), which:
- Reads the local IPA into a
Databuffer - Creates the remote directory
/var/mobile/Documents/vphone-installs - Generates a unique remote path using UUID prefixing to prevent filename collisions
Optional Code Signing Configuration
If a signing certificate is configured via Self.signCertURL(), the host uploads the certificate to the same remote directory and includes its path in the installation request under the cert_path key. This enables the guest daemon to re-sign the binary during installation.
Transmission and Guest Installation
The host transmits data through the vsock channel using createDirectory(path:) (sending file_mkdir) and uploadFile(path:data:). Once uploaded, the host constructs and sends the installation request:
var request: [String: Any] = [
"t": "ipa_install",
"path": remotePath,
"registration": "User",
]
// cert_path appended if signing certificate provided
The guest daemon processes this request, validates the package integrity, applies code signing if specified, and installs the app into the guest sandbox.
Result Handling and Cleanup
After receiving the daemon's response, the host checks resp["msg"] for installation details. If the message is empty, it returns the default success string: "Installed <file>. through the built-in IPA installer."
A defer block ensures cleanup of temporary files (both IPA and certificate) from /var/mobile/Documents/vphone-installs, maintaining VM storage hygiene. If the daemon does not support ipa_install, the system throws ControlError.guestError with instructions to reconnect or reboot the VM.
Installation Methods
Interactive Menu Installation
For GUI users, the menu-driven approach provides file selection and status feedback:
@objc func installIPAFromDisk() {
guard control.isConnected else {
showAlert(title: "Install App Package",
message: "Guest is not connected.", style: .warning)
return
}
let panel = NSOpenPanel()
panel.allowedContentTypes = VPhoneInstallPackage.allowedContentTypes
panel.message = "Choose an IPA or TIPA package to install in the guest."
if panel.runModal() == .OK, let url = panel.url {
Task {
do {
let result = try await control.installIPA(localURL: url)
showAlert(title: "Install App Package",
message: VPhoneInstallPackage.successMessage(
for: url.lastPathComponent, detail: result),
style: .informational)
} catch {
showAlert(title: "Install App Package",
message: "\(error)", style: .warning)
}
}
}
}
Command-Line Flag Installation
For scripting and automation, use the --install-ipa flag:
vphone-cli --install-ipa /path/to/MyApp.ipa
The CLI stores the URL and automatically triggers installIPA(localURL:) once the vsock channel establishes connectivity.
Programmatic API Usage
Developers integrating vPhone-CLI into larger workflows can invoke the control layer directly:
let control = VPhoneControl(connection: vsockConnection)
let ipaURL = URL(fileURLWithPath: "/tmp/MyApp.ipa")
Task {
do {
let message = try await control.installIPA(localURL: ipaURL)
print("✅ Install succeeded:", message)
} catch {
print("❌ Install failed:", error)
}
}
Key Source Files and Implementation Details
Understanding the source structure helps with debugging and extension:
-
VPhoneMenuApps.swift: ContainsbuildAppsMenu()andinstallIPAFromDisk(), handling the UI flow and validation before delegating to the control layer. -
VPhoneControl.swift(lines 54-106): Implements the coreinstallIPA(localURL:)andinstallIPAWithBuiltInInstallermethods, managing remote directory creation, certificate handling, and theipa_installprotocol request. -
VPhoneInstallPackage.swift: DefinesallowedContentTypesfor.ipaand.tipafiles, providesisSupportedFile(_:)validation, and formats success messages viasuccessMessage(for:detail:). -
VPhoneCLI.swift: Parses command-line arguments including--install-ipa, bridging CLI inputs to the control layer. -
Guest Daemon: Receives the
ipa_installmessage inside the VM (not included in the host repository) and performs the actual sandboxed installation.
Summary
- vPhone-CLI provides three interfaces for IPA installation: interactive menu, CLI flag, and programmatic API.
- The host control layer (
VPhoneControl.swift) manages file uploads to/var/mobile/Documents/vphone-installsand vsock communication. - File validation ensures only
.ipaand.tipaextensions are processed, with UUID-based naming to prevent collisions. - Optional code signing is supported by uploading certificates alongside the package and specifying
cert_pathin the installation request. - The guest daemon executes the actual installation via the
ipa_installprotocol message, returning status details to the host. - Automatic cleanup removes temporary files from the guest VM after installation completes.
Frequently Asked Questions
How do I install an IPA file when the guest daemon returns an unsupported error?
If you encounter ControlError.guestError indicating the ipa_install protocol is unsupported, the guest daemon (vphoned) requires an update. Reconnect to the VM or reboot it to ensure the daemon supports the installation protocol. The host will retry the request automatically once connectivity resumes.
Can I install unsigned IPAs using vPhone-CLI?
Yes, by providing a signing certificate through the configuration mechanism. If Self.signCertURL() returns a valid certificate path, the host uploads it to the guest and includes cert_path in the installation request. The guest daemon then re-signs the binary during installation. Without a certificate, only properly signed IPAs will install successfully.
What file formats does vPhone-CLI support for installation?
According to VPhoneInstallPackage.swift, the system supports .ipa (standard iOS App Store packages) and .tipa (testflight or development variants). The allowedContentTypes array restricts file selection dialogs to these extensions, and isSupportedFile(_:) validates the extension before upload begins.
Where does vPhone-CLI store temporary files during installation?
During the upload phase, files are stored in /var/mobile/Documents/vphone-installs inside the guest VM. The system generates unique filenames using UUID prefixes to avoid collisions. A defer block in installIPAWithBuiltInInstaller ensures these temporary files are deleted immediately after the installation completes, regardless of success or failure.
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 →