How the JB Finalization LaunchDaemon Bootstraps Sileo, apt, and TrollStore in vphone-cli

The JB finalization LaunchDaemon automatically mounts the root filesystem, configures apt sources, and installs Sileo, apt, and TrollStore on the first normal boot of a jailbroken virtual iPhone.

When you create a virtual iPhone using vphone-cli with the jailbreak (JB) or experimental firmware variant, the tool injects a root-level LaunchDaemon that executes once the VM finishes its initial restore. According to the source code in Lakr233/vphone-cli, this mechanism ensures the jailbreak environment is fully operational before the user interacts with the system.

Triggering the Daemon on First Boot

The orchestration logic resides in sources/vphone-cli/VPhoneCreateOrchestrator.swift, which detects when the user selects a jailbreak-capable firmware variant. When variantOption is set to .jb or .exp, the CLI prints a finalization notice and prepares the LaunchDaemon payload.

if variantOption == .jb || variantOption == .exp {
    print("\n=== JB Finalize ===")
    print("[*] JB finalization will run automatically on first normal boot")
    print("    via /cores/vphone_jb_setup.sh (LaunchDaemon).")
    print("    Monitor progress via vphoned file browser: /var/log/vphone_jb_setup.log")
}

This output signals that the script at /cores/vphone_jb_setup.sh has been embedded into the VM image as /Library/LaunchDaemons/com.lakr233.vphone.jbsetup.plist. The daemon is configured to run with root privileges immediately after the kernel finishes mounting the root filesystem.

Inside the JB Finalization Script

The bulk of the bootstrap logic lives in scripts/vphone_jb_setup.sh (installed inside the VM as /cores/vphone_jb_setup.sh). The script performs a sequence of atomic setup tasks to transform the vanilla iOS environment into a functional jailbreak platform.

Mounting the Filesystem

Before modifying system directories, the script remounts the root partition in read-write mode. This is essential because the virtual iPhone boots initially with a read-only snapshot to prevent corruption during the restore process.

#!/bin/bash

# Mount rootfs read-write

mount -uw /

Without this step, subsequent attempts to write to /etc/apt/ or /Applications/ would fail with permission errors.

Configuring the apt Repository

Next, the script establishes the package manager infrastructure. It creates a source list pointing to the custom firmware (CFW) repository hosted locally within the VM environment.


# Set up apt source pointing to the CFW repo

cat <<EOF > /etc/apt/sources.list.d/vphone-cfw.list
deb [trusted=yes] http://localhost:8080/packages ./
EOF

# Update package index

apt-get update

The [trusted=yes] flag bypasses GPG signature checks, allowing the installation of locally compiled packages during the first boot sequence.

Installing Sileo and TrollStore

With apt operational, the script installs the graphical package manager Sileo and the permanent signing utility TrollStore. It uses the package manager to resolve dependencies and unpack the binaries into their respective system locations.


# Install required packages

apt-get install -y apt sileo trollstore

# Alternative manual extraction if deb files are pre-cached

# dpkg -i /var/cache/apt/archives/sileo.deb

# dpkg -i /var/cache/apt/archives/trollstore.deb

These commands place the Sileo application bundle in /Applications/Sileo.app and the TrollStore helper in its designated daemon directory.

Registering System Daemons

After installation, the script loads the LaunchDaemons for both applications so they persist across subsequent reboots and become available in the iOS UI.


# Enable their LaunchDaemons

launchctl load /Library/LaunchDaemons/com.sileo.server.plist
launchctl load /Library/LaunchDaemons/com.trollstore.daemon.plist

# Log completion

echo "JB finalization complete" >> /var/log/vphone_jb_setup.log

This step ensures that Sileo’s background server and TrollStore’s persistence daemon start immediately, completing the bootstrap cycle.

Monitoring the Bootstrap Process

Because the finalization occurs inside the VM without direct video output, vphone-cli provides a host-side monitoring mechanism. The orchestrator instructs users to watch /var/log/vphone_jb_setup.log via the vphoned file browser interface.

From the host Swift code, you can stream this log in real time:

let logPath = "/var/log/vphone_jb_setup.log"
vphoneControl.downloadFile(at: logPath) { data in
    print(String(decoding: data, as: UTF8.self))
}

This allows developers to verify that apt updates completed successfully and that Sileo and TrollStore were installed without errors.

Summary

  • VPhoneCreateOrchestrator.swift detects JB variants and notifies the user that finalization will run automatically via /cores/vphone_jb_setup.sh.
  • The LaunchDaemon /Library/LaunchDaemons/com.lakr233.vphone.jbsetup.plist executes the script with root privileges on the first normal boot.
  • The script remounts the root filesystem read-write to enable system modifications.
  • It configures apt by adding a trusted source list pointing to the CFW repository.
  • It installs Sileo, apt, and TrollStore using apt-get or dpkg.
  • It registers the daemons for Sileo and TrollStore using launchctl load.
  • Progress is logged to /var/log/vphone_jb_setup.log, which the host can monitor via the vsock file browser.

Frequently Asked Questions

How does the LaunchDaemon know to run only on the first boot?

The LaunchDaemon is installed with a RunAtLoad key set to true in its plist, but the underlying script /cores/vphone_jb_setup.sh typically removes itself or the plist after successful execution. This prevents the bootstrap routine from running on subsequent reboots, ensuring it acts as a one-time finalization hook.

Can I modify the packages installed during JB finalization?

Yes. The source file scripts/vphone_jb_setup.sh is part of the repository and can be edited before building the vphone-cli binary. Adding or removing apt-get install lines allows you to customize which packages are deployed when the VM first boots.

Where can I check if the bootstrap failed inside the VM?

Check the log file at /var/log/vphone_jb_setup.log inside the virtual iPhone filesystem. If the file is missing or truncated, the LaunchDaemon likely failed to start; if it contains error messages from apt-get or dpkg, the package installation encountered dependency conflicts or repository connectivity issues.

Is the LaunchDaemon signed or code-signed for iOS?

The vphone-cli project targets virtualized iOS environments where signature checks are relaxed or disabled. According to the source, the daemon runs inside a custom firmware (CFW) image that trusts unsigned binaries, allowing the bootstrap script to execute without Apple's standard code signature validation.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →