# How to Perform IPA Installation Within a vPhone-CLI VM: Complete Technical Guide

> Learn how to perform IPA installation within a vphone-cli VM using a vsock pipeline. This technical guide details uploading, signing, and installing IPA packages.

- Repository: [Lakr/vphone-cli](https://github.com/Lakr233/vphone-cli)
- Tags: how-to-guide
- Published: 2026-09-09

---

**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`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneMenuApps.swift), the `buildAppsMenu()` function adds the *"Install IPA/TIPA…"* menu item, while [`VPhoneCLI.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneCLI.swift) exposes the `--install-ipa` flag for terminal-based workflows.

### Host-Side Control Layer

[`VPhoneControl.swift`](https://github.com/Lakr233/vphone-cli/blob/main/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`](https://github.com/Lakr233/vphone-cli/blob/main/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`](https://github.com/Lakr233/vphone-cli/blob/main/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 `Data` buffer
- 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:

```swift
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:

```swift
@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:

```bash
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:

```swift
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`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneMenuApps.swift)**: Contains `buildAppsMenu()` and `installIPAFromDisk()`, handling the UI flow and validation before delegating to the control layer.

- **[`VPhoneControl.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneControl.swift)** (lines 54-106): Implements the core `installIPA(localURL:)` and `installIPAWithBuiltInInstaller` methods, managing remote directory creation, certificate handling, and the `ipa_install` protocol request.

- **[`VPhoneInstallPackage.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneInstallPackage.swift)**: Defines `allowedContentTypes` for `.ipa` and `.tipa` files, provides `isSupportedFile(_:)` validation, and formats success messages via `successMessage(for:detail:)`.

- **[`VPhoneCLI.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneCLI.swift)**: Parses command-line arguments including `--install-ipa`, bridging CLI inputs to the control layer.

- **Guest Daemon**: Receives the `ipa_install` message 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`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneControl.swift)) manages file uploads to `/var/mobile/Documents/vphone-installs` and vsock communication.
- **File validation** ensures only `.ipa` and `.tipa` extensions are processed, with UUID-based naming to prevent collisions.
- **Optional code signing** is supported by uploading certificates alongside the package and specifying `cert_path` in the installation request.
- The **guest daemon** executes the actual installation via the `ipa_install` protocol 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`](https://github.com/Lakr233/vphone-cli/blob/main/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.