Templates
A template is a complete, frozen machine that vm create clones new machines from. The first creation with a given set of options builds it; every later one with the same options takes seconds and downloads nothing. Read this page to control how templates are built, slimmed and cleaned up.
Create machines from a template
vm create uses templates by default:
- With a matching template,
vm createclones the machine from it with a new identity, gives it the requested CPU, memory and network, and boots it once to check vphoned. This needs neither root nor the IPSWs. - Without one, it downloads the IPSWs if needed, runs the full pipeline into a staging folder, builds and freezes the template, then clones the machine from it.
--template <id>clones from a template by its identifier, or a unique prefix of four or more digits, and takes no IPSW options.--device,--preset,--disk-sizeand the slimming switches, when given, must match the template's; a clone cannot change them.--no-templaterestores the machine on its own, with keys of its own; it takes no slimming switches.
To turn a VM into a template by hand, ask which template a vm create would use, or see how Launchpad builds them, read Building and finding templates.
How a template is matched
Before anything is restored, vm create works out a template key from its options and the two IPSWs. The key covers:
- the guest device;
- the iOS and cloudOS versions and builds;
- the patch preset and the boot-chain patches it resolves to. For a preset the bundle does not ship (a preset file, or one in
~/.vphone/patches_presets), every patch it resolves to counts, guest ones included, because such a preset can change under the same identifier and a clone keeps its template's guest patches; - the bundle series (
2.9for 2.9.x); - the disk size;
- what is trimmed from the guest's System volume (
--trim) and the kept languages; - the slimming switches below.
CPU, memory, screen and network are not part of the key.
The builds come from the IPSWs when they are local files or already in the IPSW cache. Otherwise they come from a template recorded with the same two sources, as vm template find works them out; a local IPSW that has been deleted counts as not there.
Building a template
When no template matches, the full pipeline runs into .templates/.building-<id>-<uuid>/: cfw install, the offline trim, then the setup boot. The result is frozen and renamed to <library>/.templates/<id>/ in one step.
- The restore tree is removed before the freeze, whatever
--keep-artifactssays. Its ~11 GB would stay pinned for as long as the template lives, and no clone can use it.--keep-artifactskeeps it only with--no-template;vm template adoptremoves it too. - A second
vm createwith the same key waits for the first instead of restoring a second copy. - A failed build stays in its staging folder for inspection.
A template boots once while it is built, for its setup boot, and never again once it is frozen.
Offline trim
After cfw install, a template build deletes system files the guest never needs from its System volume, offline, with the volume mounted on the host. --trim on vm create (default standard) and --tier on vm template trim pick the tier:
--keep-languages (default en,zh-Hans,zh; English is always kept) chooses the languages standard keeps. The tier, the version of the list and the kept languages are part of the template key (standard/1/en,zh,zh-Hans), so templates trimmed differently never match.
Trimming cannot be undone: a clone cannot get the files back.
The deleted files free nothing at first. The guest's original system snapshot (orig-fs.disabled.rn-*, left by cfw install) still holds every block, and the host cannot delete it, even as root. The setup boot deletes it as its first step, and only then is the space returned. So a trim is refused for a template that gets no setup boot, and a trimmed template is frozen or adopted only once its snapshot is gone.
vm template trim needs no root. It runs on a stopped machine that has not been cloned from a template, or on an unfinished .building-… folder, and refuses a frozen template.
Setup boot and slimming
The setup boot finishes the template the way every clone should start. It boots the template once and, through vphoned, in this order:
- deletes the
orig-fs.disabled.rn-*APFS snapshotcfw installleft (it holds about 20 MB, plus every file trimmed from the System volume until it is gone); - skips Setup Assistant (
setup.skip); - waits for first-boot work to settle (
setup.settle, up to 10 minutes): installd expands the removable system apps on the first boot; - removes the system apps (
apps.remove_system, backups kept in the guest); - applies the service profile (
services.profile.apply), which includes turning off the sign-in follow-up daemons (followupd,appleidsetupd); - reboots, then checks: no snapshot left, Setup done, none of the profile's services running, the removed apps gone, vphoned answering;
- clears the device name
vphone-vmpinned for this boot, and shuts the guest down cleanly.
Every step has a deadline. A failed step stops the VM, records nothing and leaves the build unfrozen; vm create names the step and how to retry it.
Each choice is part of the key, so templates with different slimming live side by side and each serves only the creates that ask for it. See the watch pairing note for the service-profile limit.
Removed apps and the profile stay reversible on a clone, through vphone-launchpad-cli guest rpc or Guest System in Launchpad:
apps.restore_systemputs an app back from its backup.services.profile.apply {"profile":"none"}turns back on exactly what the profile turned off.
What a clone inherits
A clone inherits from the template: Setup done, the apps and services as the setup boot left them, the first-boot work installd and the indexers did, and the Data volume as of that boot.
It does not inherit a device name. The template's pin is cleared, so a clone shows iPhone until its own VM connects and pins the clone's name. A new identity also means the Mac asks "Trust This Computer?" again.
Shared secrets
Every machine cloned from one template shares, with the template and with each other, its SEP root secret, its Data volume keys and the data the restore and the setup boot wrote. One clone could in principle decrypt another's Data volume.
A machine that needs keys of its own, for example to sign in to Apple services for multi-device research, should be created with --no-template.
Clones get a new ECID, UDID and MAC address on their first start, as with vm clone --new-identity. On APFS they share every unchanged block with the template: a new clone costs almost nothing until it starts writing, and a slimmed template leaves it little first-boot work to write.
Manage templates
Stale templates
A template is listed as stale when this vphone-cli belongs to another bundle series, when its key has an older format, when its preset now resolves to other boot-chain patches, or when its patch receipt disagrees with its plan. A stale template is never used: vm create with its key fails and names it. Delete it to have the next vm create build a new one.
Adopting a VM
vm template adopt <vm> turns a stopped VM into a template, under the key its own records give: restore-info.json, PatchPlan.plist, config.plist, the disk image, Launchpad's launchpad.json, and the steps vm template trim and vm template setup recorded in its Template.plist. The VM leaves vm list.
Adopt a VM straight after its setup boot: every clone inherits what its guest has done since. A VM with snapshots is refused, and so is one that would be stale unless --force is given.
Frozen templates never boot
vm launch and vphone-vm refuse a frozen template, in DFU too. No machine name reaches into .templates, so vm launch, clone, export, rename and delete cannot pick one up by accident. A template that booted after being frozen would write state into the blocks every later clone inherits, and the clones made before it would stop sharing them.
Machines using a template
A machine cloned from a template records the template in TemplateSource.plist. A vm clone of it keeps the record (the copy shares the template's blocks too), and vm export leaves it out (an import shares nothing). The record also names the template's build, so a template deleted and built again with the same key does not count the machines cloned from the old one, which share none of its blocks.
vm template list and show list the machines using each template and its size on disk, and vm info shows a machine's template. When vm delete removes the last machine cloned from a template that still exists, it says so, and never deletes the template itself:
Deleting a template
vm template delete <id> removes the template; machines cloned from it keep working. The blocks they still share with it are freed only when those machines change them or are deleted, so deleting a template frees less than its size while clones remain.
The note it prints says which case applies: either the machines that use it, whose shared blocks stay allocated until they change them or are deleted, or that no machine uses it now, so deleting frees its blocks. A local Time Machine snapshot taken while the template existed may keep them until the snapshot expires. --json with --force prints the same facts.
Templates take disk space although vm list does not show them. Look in ~/.vphone/machines/.templates, and keep in mind that du counts a template and each of its clones in full.