Creating VMs
It’s important to understand that the anka
CLI VM creation, modification, etc, is all exclusively within your current user. The root user and non-root users will have different environments. You can use the Anka Build Cloud Registry to move VMs between users (and hosts).
Prerequisites
- You’ve installed the Anka Virtualization package.
- The host you wish to use has a full internet connection. If you are behind a corporate firewall/proxy, you’ll need to review https://support.apple.com/101555.
Create your first VM
You have two methods of creating your Anka VMs. We will describe both in this guide, but you only really need to choose one.
- With the anka create command (recommended).
- With the Anka.app UI.
Supported VM macOS versions
Anka allows you to create VMs for the following macOS versions:
INTEL | Anka 2.5.7 | Anka 3.x |
macOS 10.13/14 | 🛑 | ✅*** |
macOS 10.15 | ✅ | ✅ |
macOS 11.x | ✅ | ✅ |
macOS 12.x | ✅ | ✅ |
macOS 13.x* | ✅ | ✅ |
macOS 14.x | 🛑 | ✅ |
macOS 15.x | 🛑 | ✅ |
Apple/ARM | Anka 3.x |
🛑 | |
🛑 | |
🛑 | |
✅ | |
✅** | |
✅** |
(*) Apple has limited the ability to install Ventura to specific hardware models. You can view a list of supported models here.
(**) When creating a 15.x VM on a host with 15.x, you must run them on the same hardware type as well as ensure the hosts have 15.x. This is a limitation from Apple. Creation of 15.x VMs on hosts with 14.x should not have this problem.
(**) ARM USERS: To run macOS 14.x VMs, you must have macOS 14.x (or higher) on your host. 13.x VMs also require a minimum host macOS version of 13.x.
(**) ARM USERS: When creating 15.x VMs on 14.x hosts, you must ensure that Xcode 16.1 OR the MobileDevice.pkg (inside of Xcode.app) is installed.
sudo xcodebuild -license accept sudo xcodebuild -runFirstLaunch for PKG in $(/bin/ls /Applications/Xcode.app/Contents/Resources/Packages/*.pkg); do sudo /usr/sbin/installer -pkg "$PKG" -target / done
(***) Requires installing a kext (https://github.com/pmj/virtio-net-osx) on the VM for networking to function.
ARM USERS: There is also a rare problem where your Xcode is not fully set up and still creates problems. Be sure to run the following:
sudo xcodebuild -license accept sudo xcodebuild -runFirstLaunch for PKG in $(/bin/ls /Applications/Xcode.app/Contents/Resources/Packages/*.pkg); do sudo /usr/sbin/installer -pkg "$PKG" -target / done
Apple’s .app installer files are currently not supported on ARM. Instead, you’ll need to obtain .ipsw files.
VM creation requires a full internet connection or access to the Apple URLs detailed on https://support.apple.com/101555. If you are behind a corporate firewall/proxy, you’ll need to set up a proxy that has the access you need and tell the system to use that proxy with the following:
# networksetup is an alternative to going into the System Preferences > Network > <interface> > Details > Proxies and setting it up manually networksetup -setwebproxy <interface> <proxyURL> <port> networksetup -setsecurewebproxy <interface> <proxyURL> <port> export http_proxy=http://<proxyURL>:<port> export https_proxy=http://<proxyURL>:<port>
Using anka create
> anka create --help
usage: create [options] [name] [macOS version/installer file/installer url]
Creates a VM Template
arguments:
name VM name
macOS version/installer file/installer url
MacOS version (see --list), installer file location, or installer URL to use for creation (example: 'latest')
options:
-m,--ram-size <val> Specify the VM RAM size (supported suffixes: T|G|M|K)
-c,--cpu-count <val> Specify the number of vCPU cores for the VM (3 or more is recommended)
-d,--disk-size <val> Specify the VM disk size (supported suffixes: T|G|M|K)
--no-setup Do not perform automated macOS setup
-q,--quiet Do not show progress
-l,--list List available macOS versions to install
You can bring you own .ipsw
and .app
files to use with anka create
. This is an alternative to specifying the version from --list
. It supports three different methods:
1. The specific macOS version from --list
ARM USERS: At the moment Apple only provides a public endpoint to list the latest macOS version.anka create --list
will therefore only show a single version. We are working to get them to publically list allipsw
. In the meantime, Intel Anka does show all archived macOS versions for.app
.
bash$ anka create -l
+---------------+---------+----------------------+
| version | build | post_date |
+---------------+---------+----------------------+
| 11.7.2 | 20G1020 | Dec 13 13:14:48 2022 |
+---------------+---------+----------------------+
| 12.6.2 | 21G320 | Dec 13 13:13:39 2022 |
+---------------+---------+----------------------+
| 13.1 (latest) | 22C65 | Dec 13 13:08:36 2022 |
+---------------+---------+----------------------+
| 13.0.1 | 22A400 | Nov 9 13:02:34 2022 |
. . .
bash$ anka create 11.7.2 11.7.2
75% [||||||||||||||||||||||||||||||||||||||||||||| ] 16:15 ETA
2. The location/path to the ipsw
or .app
on the host
bash$ anka create --cpu-count 5 --disk-size 100G 12.5.1 /Applications/macos-12.5.1.app
. . .
3. The URL to download the ipsw
from (.app not supported)
bash$ anka create --cpu-count 5 --disk-size 100G 12.5.1 https://myCompanyIntranet/UniversalMac_13.1_22C65_Restore.ipsw
. . .
ARM USERS: The ipsw files will be downloaded intoimg_lib_dir
. You can find the location of this directory withanka config img_lib_dir
. These (and other temporary) files can be deleted withanka delete --cache
.
A few tips when creating VMs:
We recommend naming your initial VM after the version of macOS.
Remember that VM templates are created under a specific user and will not be available to other users.
VM performance is important to our users. When setting CPUs for the VMs, 2vCPUs is usually not enough and can cause instability inside of the VM.
- ARM USERS: VCPUs are determined by taking the physical performance cores and multiplying by 2. This means you can set the CPU on creation for an M1 mini with 4 physical perf cores to
anka create --cpu-count 4
, and run two VMs per host (8vCPUs available). - INTEL USERS: We recommend taking the total physical cores, doubling it, and then subtracting 2cpu. This leaves you with total virtual cores that can be used by VMs. If you plan to run 2 VMs at a time, divide the total vCPU in half and give the VM the result.
- ARM USERS: VCPUs are determined by taking the physical performance cores and multiplying by 2. This means you can set the CPU on creation for an M1 mini with 4 physical perf cores to
If you experience issues, run
anka --debug create. . .
and provide it to Veertu’s support.You can re-enable SIP on intel VMs with
anka modify {vmNameOrUUID} set custom-variable sys.csr-active-config 0
post-create.
RAM, DISK, and CPU are all set from the defaults under the Anka configuration:
❯ anka config | grep default | default_disk | 137438953472 | | default_nvcpu | 4 | | default_ram | 4294967296 |
INTEL USERS: Suspending VMs can sometimes produce a VM which is frozen on start. Usually this is because the hardware & cpu type you created the VM and suspended it on is different from the one you’re trying to start it on. Be sure to suspend your VMs on the same hardware that will be running VMs.
Anka Develop license (default): While you can create as many VMs as you wish, the free Anka Develop license only allows you to run one VM at a time and will only function on laptops (Macbook, Macbook Pro, and Macbook Air). It only supports a stopped VM state.
Anka Build license: When determining how many vcpus and ram your VM needs, you can divide the number of VMs you plan on running simultaneously within a host by the total virtual cores (vcpus) it has. So, if I have 12vCPUs on my 6core Mac Mini, and I want to allow 2 running VMs at once and not cripple the host machine, I will set the VM Template/Tag to have 6vcpus (12 / 2). However, with RAM, you’ll need to allow ~2GB of memory for the Anka Software and host ((totalRAM / 2)-1). Build licenses support suspended and stopped VM states.
Be aware of the user you’re executing Anka CLI commands as. If you create VMs as root, they won’t be available to other users on the system and vice versa.
After executing anka create
, Anka will automatically set up macOS, create the user anka
with password: admin
, disable SIP, and enable VNC for you. The VM will then be stopped.
Using the Anka GUI
- Click on Create new VM.
- LEAVE INSTALLER BLANK and click on Options to set any non-default values you want.
Leaving the installer blank will automatically target the latest macOS version, pulling the IPSW file from the official Apple CDN (
updates.cdn-apple.com
). You can use your own IPSW file with the Anka CLI instead. - Be patient while it’s creating.
Once the VM is created, you will see it on the sidebar – Hooray!
Set up the VM (post-GUI creation)
This is not needed if you ran anka create
.
The GUI tool will not automatically set up macOS and requires you to perform several steps manually.
- Start the VM with
anka start -uv
to launch the Anka Viewer and addons. Please do not use-uv
in your scripts when starting VMs. It is only for interactive/logged in sessions.
anka view
does not currently work post-start unless you started it with -v.- ARM USERS:
sudo anka view
as a normal user is not possible yet. You’ll need to ensure that VNC is enabled to access VMs running undersudo
.
Once inside the Anka Viewer/VM, finish the macOS installation and be sure to install the addons package through the disk we mounted with
-u
.After you’re finished, reboot the VM.
For our addons to install and enable autologin properly, you need to create the VM user as username:anka
and password:admin
. If you decide to use your own username and password, you will need to manually enable autologin for the user.
Disable SIP in Recovery Mode (post-GUI creation)
You can start the VM in Recovery Mode with
ANKA_START_MODE=2
:ANKA_START_MODE=2 anka start 12.6
SIP is only enabled for VMs created in the Anka App’s UI. These instructions are irrelevant for VMs created with anka create
.
With SIP enabled, there are two main issues you’ll find when running VMs:
- User or command executions can hang due to a “allowed to access” dialog in the VM’s UI. It requires VNC access and manual intervention to get around (no commands to disable this protection feature).
- Apple’s
syspolicyd
will notice applications and processes running for the first time and consume a lot of CPU and RAM trying to scan them.
In order to disable SIP, you need to first launch the VM in recovery mode.
Then, you launch the Terminal application and execute csrutil disable
. Once executed and after confirmation that the command worked, you can stop the VM. On next boot, SIP will be disabled.
Optimizing your VM
It’s recommended that you disable:
- Spotlight and
coreduetd
:
# Disable indexing volumes
sudo defaults write ~/.Spotlight-V100/VolumeConfiguration.plist Exclusions -array "/Volumes" || true
sudo defaults write ~/.Spotlight-V100/VolumeConfiguration.plist Exclusions -array "/Network" || true
sudo killall mds || true
sleep 60
sudo mdutil -a -i off / || true
sudo mdutil -a -i off || true
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist || true
sudo rm -rf /.Spotlight-V100/*
rm -rf ~/Library/Metadata/CoreSpotlight/ || true
killall -KILL Spotlight spotlightd mds || true
sudo rm -rf /System/Volums/Data/.Spotlight-V100 || true
- SIP, as
syspolicyd
will scan running processes and slow everything down.
Listing available VMs in the CLI
❯ anka list
+----------------------+--------------------------------------+---------------------+---------+
| name | uuid | creation_date | status |
+----------------------+--------------------------------------+---------------------+---------+
| 12.2.0-arm (vanilla) | a6f24306-2af7-45ed-9d70-3a3c1ee7f03a | Jan 6 12:34:52 2022 | stopped |
+----------------------+--------------------------------------+---------------------+---------+
| test_vm1 | 565e47ce-a9f9-4ac8-81bc-645d48473de1 | Jan 6 12:34:52 2022 | stopped |
+----------------------+--------------------------------------+---------------------+---------+
❯ anka --machine-readable list | jq
{
"status": "OK",
"body": [
{
"name": "12.2.0-arm",
"uuid": "a6f24306-2af7-45ed-9d70-3a3c1ee7f03a",
"creation_date": "2022-01-06T12:34:52Z",
"version": "vanilla",
"status": "stopped"
},
{
"name": "test_vm1",
"uuid": "565e47ce-a9f9-4ac8-81bc-645d48473de1",
"creation_date": "2022-01-06T12:34:52Z",
"status": "stopped"
}
]
}
❯ anka --machine-readable list --field name --field version | jq
{
"status": "OK",
"body": [
{
"name": "12.2.0-arm",
"version": "vanilla"
},
{
"name": "test_vm1"
}
]
}
Stop or Suspend the VM
Suspending VMs is only possible on intel currently.
This is not necessary for anka modify
commands.
Once you’ve finalized your changes inside of the VM, be sure to use anka stop
or anka suspend
.
> anka stop --help
usage: stop [options] [vmid...]
Shut down a VM(s)
arguments:
vmid VMs to stop
options:
-a,--all Shutdown all running VMs
-f,--force Forcefully stop the VM(s)
> anka suspend --help
usage: suspend [options] [vmid...]
Suspend a running VM(s)
arguments:
vmid VM to suspend
options:
-a,--all Suspend all running VMs
Deleting a VM
Anka CLI
❯ anka delete test
are you sure you want to delete vm 77f33f4a-75c3-47aa-b3f6-b99e7cdac001 test [y/N]:
Anka GUI
VM Clones
Disk Optimization
Customers coming from Anka 2 will know that when you clone a VM (untagged or tagged), it will share the underlying VM image files between the two. However, this is not the case for Anka 3. As of right now, sharing of the underlying VM image files between a clone and its source requires first creating a tag for the source before you clone. You can do this with anka push --local
, or just a regular anka push
if you’re running the Anka Build Cloud Registry. Don’t worry, clones will not have access to change the original source VM state.
> anka push --help
usage: push [options] vmid [remote]
Push a VM to the registry
arguments:
vmid VM to push
remote Sets an alternate registry
options:
-t,--tag <val> Set the tag name to push (mandatory)
-v,--remote-vm <val> Registry template to push the tag onto
-d,--description <val> Set textual description of the tag
-f,--force Forcefully push, regardless of a tag already existing
-l,--local Commit the template without pushing it to the Registry
-s,--shallow Include all the changes of an older tags
-q,--quiet Do not show progress
❯ anka list
+--------+--------------------------------------+----------------------+---------+
| name | uuid | creation_date | status |
+--------+--------------------------------------+----------------------+---------+
| 12.0.1 | 002b73b6-dc99-4d6b-8f68-6067a3a66d73 | Nov 19 08:02:33 2021 | stopped |
+--------+--------------------------------------+----------------------+---------+
❯ anka push --local --tag vanilla 12.0.1
❯ anka list
+------------------+--------------------------------------+----------------------+---------+
| name | uuid | creation_date | status |
+------------------+--------------------------------------+----------------------+---------+
| 12.0.1 (vanilla) | 002b73b6-dc99-4d6b-8f68-6067a3a66d73 | Nov 19 08:02:33 2021 | stopped |
+------------------+--------------------------------------+----------------------+---------+
The above example shows the tag “vanilla” does not exist locally until we execute the anka push --local
.
Cloned VMs will use a trivial amount of disk space until you start them. Once started, an empty image is created and connected on top of existing images and any changes to or in macOS are then added to it.
To switch between tags locally, you can use the
anka pull --local --tag {targetTagname} {VMName}
command:> anka pull --help usage: pull [options] vmid [remote] Pull a VM template from the registry arguments: vmid VM to pull remote Sets an alternate registry options: -t,--tag <val> Pull the particular tag (latest if not specfied) -l,--local Checkout (make it current) local tag --fetch-only Download tag without checkout -s,--shrink Delete other local tags to optimize disk usage --check-download-size Get the tag size only -q,--quiet Do not show progress
Cloning
You can easily create VM clones from a source VM and its current state using anka clone
:
> anka clone --help
usage: clone [options] vmid [name...]
Clone a VM
arguments:
vmid VM to clone
name New VM name(s)
options:
-c,--copy Create an independent copy
-t,--tag <val> Clone particular VM tag (should be available locally)
Don’t worry, at no point do clones have access to change the original source VM state.
All clones share as many underlying layers and data as possible.
There are two types of cloning you can perform:
- Shallow Clone:
anka clone {source} {dest}
– Shallow clones allow you to get a distinct entity, separate from the source, with a new name and UUID. - Full Clone:
anka clone --copy {source} {dest}
– Full clones create a copy that merges all underlying layers so that they cannot be shared with other VMs. While this could theoretically shrink the size of the VM, it loses the ability to re-use existing layers from other VMs on the host and can actually use more disk space than before.
❯ anka list
+------------------+--------------------------------------+----------------------+---------+
| name | uuid | creation_date | status |
+------------------+--------------------------------------+----------------------+---------+
| 12.0.1 (vanilla) | 002b73b6-dc99-4d6b-8f68-6067a3a66d73 | Nov 19 08:02:33 2021 | stopped |
+------------------+--------------------------------------+----------------------+---------+
❯ anka clone 12.0.1 12.0.1-xcode13
6070ee59-6c16-4c93-ba7a-122b66b1472a
❯ anka list
+------------------+--------------------------------------+----------------------+---------+
| name | uuid | creation_date | status |
+------------------+--------------------------------------+----------------------+---------+
| 12.0.1 (vanilla) | 002b73b6-dc99-4d6b-8f68-6067a3a66d73 | Nov 19 08:02:33 2021 | stopped |
+------------------+--------------------------------------+----------------------+---------+
| 12.0.1-xcode13 | 6070ee59-6c16-4c93-ba7a-122b66b1472a | Nov 19 08:02:33 2021 | stopped |
+------------------+--------------------------------------+----------------------+---------+
Note for Intel Usersanka show
output will indicate the logical size (what you set withanka create --disk
or withanka modify {vm} disk
) and also “on disk” usage. The “on disk” usage is a combination of all shared data and not unique usage for itself if the VM is cloned from another. Unique usage can be obtained usinganka run {vmname} bash -c "df -h"
.
VM Templates
Once a VM has been tagged, it becomes a “VM Template”. The VM template & tag’s state cannot be permanently modified unless you create a new tag, post-changes. This is very reminiscent of how git commit
works. You can execute commands and modify the state of the VM after tagging it, but it will not save the changes until you create a new tag. This is important to consider when using the Anka Build Cloud Registry since it will only push the state of the VM when the tag was created, not after.
In summary, when cloning a tagged VM you have two options:
- Shallow Clone from the current VM state, regardless of the state when it was tagged (
anka clone {source} {clone}
). - Shallow Clone the state of a VM template & tag by targeting the tag by name (
anka clone --tag {tagName} {source} {clone}
), regardless of what has been done to it since tagging.
Clones are not automatically tagged.
❯ anka list | grep test
| test (v1) | ff06aa5b-0825-4f86-b5d0-c1cdb39fcedf | Jan 25 13:15:10 2022 | stopped |
❯ anka clone --tag v1 test test3
8a4e0033-29b4-4c29-8a0c-51fa53093d1c
❯ anka list | grep test
| test3 | 8a4e0033-29b4-4c29-8a0c-51fa53093d1c | Feb 3 12:01:34 2022 | stopped |
| test (v1) | ff06aa5b-0825-4f86-b5d0-c1cdb39fcedf | Jan 25 13:15:10 2022 | stopped |
Our Recommendation for Templates
If you’re managing multiple templates for multiple teams and projects, you want to share as many underlying layers in the hierarchy of VM Templates as possible. To do this, we typically recommend:
- Create a VM with macOS
13.0.1
and also name it that. The, push or locally tag it asvanilla
. - Start the
13.0.1
VM and add the dependencies that everyone would need (typically git and brew). Stop the VM and modify to add port forwarding. Push/locally tag this asbrew+git+portforwarding22
. - Clone from
13.0.1
(with thebrew+git+portforwarding22
tag) and create13.0.1-xcode14.1
. Start it and install Xcode. Stop it and push it with any tag name. I usev1
usually. - Clone from
13.0.1-xcode14.1
and create13.0.1-xcode14.1-{projectNameHere}-v1
which you’ll install all of that projects dependencies in and push with any tag name.
This allows everything to share the underlying layers that are the same (since they’re all cloned from 13.0.1
) and optimize disk space. You can then just pull the last VM template in the hierarchy and create a new one when needed, telling the teams to point to the new one when ready.
ARM USERS: Suspending will currently stop the VM. It will show as suspended
, regardless.
If it helps, here is it visually:
13.0.1 (stopped) |
| -> clone -> 13.0.1-xcode14.1 (stopped) |
| | -> clone -> 13.0.1-xcode14.1-project1-v1 (with fastlane-v1.X) (suspended)
| | -> clone -> 13.0.1-xcode14.1-project2-v1 (with fastlane-v2.X) (suspended)
| | -> clone -> 13.0.1-xcode14.1-project2-v2 (with fastlane-v2.X) (suspended)
|
| -> clone -> 13.0.1-xcode13.4.1 (stopped) -> clone -> 13.0.1-xcode13.4.1-project3-v1 (suspended)
Exporting and Importing VMs
Export
- Only available for Enterprise or Enterprise Plus licenses.
- Exporting a VM is performing a unique copy like
anka clone -c
would do if it has no tags. - If you export a tagged VM in a chain (a VM that was cloned from another, or a tag on top of another VM tag), it will only export the VM layers that relate to that tag. You have to export and import all tags in the order they were created. This adds a fair bit of complexity though as each VM Tag is its own separate layer. When exporting, you’ll need to ensure the target is active on the host. To make it active, you can
anka pull --tag 1 templateA
(--local
may speed this up if it was already pulled). Once active, exporting it requires--tag <val>
.
This feature does not work if chunk_size
is in use for the VM templates/tags.
> anka export --help
usage: export [options] vmid file
Export a VM as an archive
arguments:
vmid VM to export
file Path to archive file
options:
-t,--tag <val> Export local VM tag
-c,--copy Include base tags into the archive
Import
> anka import --help
usage: import [options] file
Import VM from an archive
arguments:
file Archive with an exported VM
options:
--fetch-only Import tag without checkout
Anka Build Cloud
Add the Registry
This is not needed on all Nodes connecting to the Controller. Most users have a “builder machine” that has the registry connection and is used to create and push VM Templates/Tags.
Assuming you haven’t changed the default port configuration, your Registry is serving requests on port 8089
.
We now need to configure the Registry on this machine so we can push/upload the local VM Template so other machines connected to the Anka Build Cloud. Uploading the Template to the Registry makes it possible to download and run it from other nodes.
sudo anka registry add <registry name> http://<ip>:8089
Verify the configuration:
sudo anka registry list-repos
++
++
<registry name you set> (default)
+--------+------------------+
| host | <the ip you set> |
+--------+------------------+
| scheme | http |
+--------+------------------+
| port | 8089 |
+--------+------------------+
Then, confirm the registry list command shows your VM Template:
sudo anka registry list
(Anka Build Cloud only) Push the VM to the Registry
sudo anka registry -r http://anka.registry:8089 push 12.X -t base
In the example above,-r {URL}
is used, but is not required if you’ve added the Registry usinganka registry add
.
After the push completes, you should see your new Template in the “Templates” section of the controller UI.