# How to Install Custom Firmware (CFW) with vphone-cli: Complete Technical Guide

> Install Custom Firmware CFW with vphone-cli. This technical guide details mounting Disk.img, copying patched files, and atomically switching boot snapshots for a seamless CFW installation.

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

---

**TLDR:** vphone-cli installs Custom Firmware (CFW) by mounting the virtual iPhone’s **Disk.img** on the host, copying patched system files and Cryptexes onto APFS volumes, and atomically switching the boot snapshot to the modified "live" volume using a coordinated two-script workflow.

Installing Custom Firmware on a virtual iPhone requires precise manipulation of APFS containers and system binaries. The **Lakr233/vphone-cli** project automates this complex process through a dual-stage shell script architecture that handles disk attachment, binary patching, and snapshot management. This guide explains exactly how CFW installation works, from mounting the raw disk image to flipping the boot snapshot for persistent modifications.

## CFW Installation Architecture

The installation process is orchestrated by two distinct scripts that separate host-level disk operations from guest-level system modifications.

### Host-Side Orchestration Script

The [`scripts/cfw_install_host.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/cfw_install_host.sh) script manages the host-level disk attachment and snapshot switching. According to the source code, it performs the following operations:

- Attaches the VM’s **Disk.img** as a raw block device using macOS disk utilities
- Identifies the APFS container and locates the *System* volume within the virtual disk
- Re-executes with **root** privileges (required for owners-honored mounts)
- Invokes the appropriate variant-specific installer based on the `--variant` flag
- Flips the boot snapshot offline using [`tools/apfs_snap_rename.py`](https://github.com/Lakr233/vphone-cli/blob/main/tools/apfs_snap_rename.py) after the installer completes, ensuring the VM boots the freshly-patched volume on next launch

### Variant-Specific Installer

The [`scripts/cfw_install.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/cfw_install.sh) (default "regular" variant) executes the actual system modifications inside the mounted APFS volumes. This script leverages [`scripts/patchers/cfw.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw.py) to extract Cryptexes from the IPSW’s BuildManifest and performs comprehensive system patching.

## Step-by-Step Installation Process

### Prerequisites and Initial Setup

Before installing CFW, the virtual machine must be in a restored state with the Disk.img created from a valid IPSW. Ensure the VM is powered off to prevent file system corruption during mounting.

```bash

# Prepare a restored VM (run once)

make restore        # Downloads an IPSW and creates vm/Disk.img

make poweroff       # Ensures the VM is not running

```

### Mounting and Modifying the Disk Image

The host script attaches Disk.img as a raw block device and determines the correct APFS container. It requires root privileges to mount the System volume with owners honored.

```bash

# Install the regular CFW (default variant)

sudo scripts/cfw_install_host.sh

# Or use the Makefile shortcut: make cfw_install

```

The script automatically selects the installation variant. You can specify alternative variants using command-line flags:

```bash
sudo scripts/cfw_install_host.sh --variant jb   # Jailbreak CFW

sudo scripts/cfw_install_host.sh --variant dev  # Development CFW  

sudo scripts/cfw_install_host.sh --variant exp  # Experimental CFW

```

### Binary Patching and System Injection

Once the System volume is mounted, [`scripts/cfw_install.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/cfw_install.sh) performs the following modifications as implemented in [`scripts/patchers/cfw.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw.py):

- **Cryptex Extraction**: Extracts system Cryptexes from the IPSW BuildManifest and copies them to the appropriate APFS volume locations
- **Binary Patching**: Modifies several critical system binaries including `seputil`, `launchd_cache_loader`, and `mobileactivationd` (preserving original backups with `.bak` extensions)
- **iOS 27 Compatibility**: Optionally patches iOS-27-specific components such as `diskimagesiod`, IOMFB size parameters, and DSC maxSlide values
- **Symbolic Link Creation**: Establishes required `dyld` symlinks for dynamic library loading

### Driver and Daemon Deployment

The installer injects additional system components not present in the stock IPSW:

- **GPU Acceleration**: Installs the **AppleParavirtGPUMetalIOGPUFamily** driver for paravirtualized graphics support
- **Jailbreak Environment**: Deploys `iosbinpack64` containing jailbreak user-land binaries
- **Host Communication**: Compiles and signs the **vphoned** Objective-C daemon using the private signing certificate bundled in `scripts/cfw_input/`
- **Launch Daemon Injection**: Modifies `launchd.plist` to register additional services including `dropbear` (SSH), `trollvnc` (VNC), and `rpcserver_ios`

### Boot Snapshot Switching

After file modifications complete, [`scripts/cfw_install_host.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/cfw_install_host.sh) invokes [`tools/apfs_snap_rename.py`](https://github.com/Lakr233/vphone-cli/blob/main/tools/apfs_snap_rename.py) to atomically switch the APFS boot snapshot from the recovery image to the live, modified system volume. This operation makes the CFW installation persistent and bootable.

### Booting the Modified System

Once the snapshot is switched, boot the virtual iPhone to access the CFW environment:

```bash
make boot

```

The system boots into the modified volume with SSH available on **port 22222** using the default password `alpine`.

## Idempotent Installation Behavior

The vphone-cli CFW installation is designed to be **idempotent**. Running the installation script multiple times safely reuses already-extracted Cryptexes, re-signs binaries from their `*.bak` copies, and overwrites existing files without corruption. This allows for iterative development and testing of custom firmware modifications.

## Summary

- vphone-cli uses a **two-stage installation process**: [`scripts/cfw_install_host.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/cfw_install_host.sh) handles disk attachment and snapshot switching, while [`scripts/cfw_install.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/cfw_install.sh) performs binary patching
- The host script requires **root privileges** to mount APFS volumes with owners honored and uses [`tools/apfs_snap_rename.py`](https://github.com/Lakr233/vphone-cli/blob/main/tools/apfs_snap_rename.py) to flip the boot snapshot
- **Binary patching** via [`scripts/patchers/cfw.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw.py) modifies critical components like `seputil`, `launchd_cache_loader`, and `mobileactivationd` while preserving backups
- The installer deploys additional drivers (**AppleParavirtGPUMetalIOGPUFamily**), jailbreak tools (`iosbinpack64`), and the **vphoned** communication daemon
- Installation supports multiple variants (`--variant jb`, `dev`, `exp`) selectable via command-line flags
- The process is **idempotent**, allowing safe re-installation without re-extracting Cryptexes

## Frequently Asked Questions

### What file system does vphone-cli modify during CFW installation?

vphone-cli modifies the **APFS** (Apple File System) volumes contained within the virtual iPhone's **Disk.img**. Specifically, it mounts the System volume to inject Cryptexes, patched binaries, and launch daemons, then uses [`tools/apfs_snap_rename.py`](https://github.com/Lakr233/vphone-cli/blob/main/tools/apfs_snap_rename.py) to switch the boot snapshot from the recovery image to the modified live volume.

### Why does the CFW installation require root privileges?

Root privileges are required for **owners-honored mounts** of the APFS volumes. When the host script [`scripts/cfw_install_host.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/cfw_install_host.sh) attaches Disk.img, it must mount the virtual iPhone's file system with full ownership permissions to preserve Unix permissions, extended attributes, and special file modes (like setuid binaries) during the copy and patching operations.

### Which binaries does the CFW patcher modify?

According to [`scripts/patchers/cfw.py`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/patchers/cfw.py), the patcher modifies several critical system binaries including **seputil**, **launchd_cache_loader**, and **mobileactivationd**, along with their backups. For iOS 27 compatibility, it also patches **diskimagesiod**, adjusts IOMFB size parameters, and modifies DSC maxSlide values. All modifications preserve the original files with `.bak` extensions for safe recovery.

### Can I install multiple CFW variants on the same Disk.img?

Yes, the installation process is **idempotent** and supports switching between variants using the `--variant` flag (options include `jb` for jailbreak, `dev` for development, and `exp` for experimental). Running `sudo scripts/cfw_install_host.sh --variant [type]` will re-patch the existing installation with the selected variant's specific modifications, reusing already-extracted Cryptexes and re-signing binaries from their preserved `*.bak` copies.