![Tart – open source virtualization for your automation needs](Resources/TartSocial.png) *Tart* is a virtualization toolset to build, run and manage macOS and Linux virtual machines on Apple Silicon. Built by CI engineers for your automation needs. Here are some highlights of Tart: * Tart uses Apple's own `Virtualization.Framework` for [near-native performance](https://browser.geekbench.com/v5/cpu/compare/14966395?baseline=14966339). * Push/Pull virtual machines from any OCI-compatible container registry. * Use Tart Packer Plugin to automate VM creation. * Built-in CI integration. *Tart* is already adopted by several automation services:

## Usage Try running a Tart VM on your Apple Silicon device running macOS Monterey or later (will download a 25 GB image): ```shell brew install cirruslabs/cli/tart tart clone ghcr.io/cirruslabs/macos-monterey-base:latest monterey-base tart run monterey-base ``` ![tart VM view app](Resources/TartScreenshot.png) ## CI Integration Tart itself is only responsible for managing virtual machines, but we've built Tart support into a tool called Cirrus CLI also developed by Cirrus Labs. [Cirrus CLI](https://github.com/cirruslabs/cirrus-cli) is a command line tool with one configuration format to execute common CI steps (run a script, cache a folder, etc.) locally or in any CI system. We built Cirrus CLI to solve "But it works on my machine!" problem. Here is an example of a `.cirrus.yml` configuration file which will start a Tart VM, will copy over working directory and will run scripts and [other instructions](https://cirrus-ci.org/guide/writing-tasks/#supported-instructions) inside the virtual machine: ```yaml task: name: hello macos_instance: # can be a remote or a local virtual machine image: ghcr.io/cirruslabs/macos-monterey-base:latest hello_script: - echo "Hello from within a Tart VM!" - echo "Here is my CPU info:" - sysctl -n machdep.cpu.brand_string - sleep 15 ``` Put the above `.cirrus.yml` file in the root of your repository and run it with the following command: ```shell brew install cirruslabs/cli/cirrus cirrus run ``` ![Cirrus CLI Run](Resources/TartCirrusCLI.gif) [Cirrus CI](https://cirrus-ci.org/) already leverages Tart to power its macOS cloud infrastructure. The `.cirrus.yml` config from above will just work in Cirrus CI and your tasks will be executed inside Tart VMs in our cloud. **Note:** Cirrus CI only allows [images managed and regularly updated by us](https://github.com/orgs/cirruslabs/packages?tab=packages&q=macos). ### Retrieving artifacts from within Tart VMs In many cases there is a need to retrieve particular files or a folder from within a Tart virtual machine. For example, the below `.cirrus.yml` configuration defines a single task that builds a `tart` binary and exposes it via [`artifacts` instruction](https://cirrus-ci.org/guide/writing-tasks/#artifacts-instruction): ```yaml task: name: Build macos_instance: image: ghcr.io/cirruslabs/macos-monterey-xcode:latest build_script: swift build --product tart binary_artifacts: path: .build/debug/tart ``` Running Cirrus CLI with `--artifacts-dir` will write defined `artifacts` to the provided local directory on the host: ```bash cirrus run --artifacts-dir artifacts ``` Note that all retrieved artifacts will be prefixed with the associated task name and `artifacts` instruction name. For the example above, `tart` binary will be saved to `$PWD/artifacts/Build/binary/.build/debug/tart`. ## Virtual Machine Management ### Creating from scratch Tart supports macOS and Linux virtual machines. All commands like `run` and `pull` work the same way regarding of the underlying OS a particular VM image has. The only difference is how such VM images are created. Please check sections below for [macOS](#creating-a-macos-vm-image-from-scratch) and [Linux](#creating-a-linux-vm-image-from-scratch) instructions. #### Creating a macOS VM image from scratch Tart can create VMs from `*.ipsw` files. You can download a specific `*.ipsw` file [here](https://ipsw.me/) or you can use `latest` instead of a path to `*.ipsw` to download the latest available version: ```shell tart create --from-ipsw=latest monterey-vanilla tart run monterey-vanilla ``` After the initial booting of the VM you'll need to manually go through the macOS installation process. As a convention we recommend creating an `admin` user with an `admin` password. After the regular installation please do some additional modifications in the VM: 1. Enable Auto-Login. Users & Groups -> Login Options -> Automatic login -> admin. 2. Allow SSH. Sharing -> Remote Login 3. Disable Lock Screen. Preferences -> Lock Screen -> disable "Require Password" after 5. 4. Disable Screen Saver. 5. Run `sudo visudo` in Terminal, find `%admin ALL=(ALL) ALL` add `admin ALL=(ALL) NOPASSWD: ALL` to allow sudo without a password. #### Creating a Linux VM image from scratch ```bash # Create a bare VM tart create --linux ubuntu # Install Ubuntu tart run --disk focal-desktop-arm64.iso ubuntu # Run VM tart run ubuntu ``` After the initial setup please make sure your VM can be SSH-ed into by running the following commands inside your VM: ```shell sudo apt update sudo apt install -y openssh-server sudo ufw allow ssh ``` ### Configuring a VM By default, a tart VM uses 2 CPUs and 4 GB of memory with a `1024x768` display. This can be changed with `tart set` command. Please refer to `tart set --help` for additional details. ### Building with Packer Please refer to [Tart Packer Plugin repository](https://github.com/cirruslabs/packer-plugin-tart) for setup instructions. Here is an example of a template to build `monterey-base` local image based of a remote image: ```json { "builders": [ { "name": "tart", "type": "tart-cli", "vm_base_name": "tartvm/vanilla:latest", "vm_name": "monterey-base", "cpu_count": 4, "memory_gb": 8, "disk_size_gb": 32, "ssh_username": "admin", "ssh_password": "admin", "ssh_timeout": "120s" } ], "provisioners": [ { "inline": [ "echo 'Disabling spotlight indexing...'", "sudo mdutil -a -i off" ], "type": "shell" }, # more provisioners ] } ``` Here is a [repository with Packer templates](https://github.com/cirruslabs/macos-image-templates) used to build [all the images managed by us](https://github.com/orgs/cirruslabs/packages?tab=packages&q=macos). ### Working with a Remote OCI Container Registry For example, let's say you want to push/pull images to a registry hosted at https://acme.io/. #### Registry Authorization First, you need to log in and save credential for `acme.io` host via `tart login` command: ```shell tart login acme.io ``` Credentials are securely stored in Keychain. #### Pushing a Local Image Once credentials are saved for `acme.io`, run the following command to push a local images remotely with two tags: ```shell tart push my-local-vm-name acme.io/remoteorg/name:latest acme.io/remoteorg/name:v1.0.0 ``` #### Pulling a Remote Image You can either pull an image: ```shell tart pull acme.io/remoteorg/name:latest ``` ...or instantiate a VM from a remote image: ```shell tart clone acme.io/remoteorg/name:latest my-local-vm-name ``` This invocation calls the `tart pull` implicitly (if the image is not being present) before doing the actual cloning. ## FAQ
How Tart is different from Anka Under the hood Tart is using the same technology as Anka 3.0 so there should be no real difference in performance or features supported. If there is some feature missing please don't hesitate to [create a feature request](https://github.com/cirruslabs/tart/issues). Instead of Anka Registry, Tart can work with any OCI-compatible container registry. Tart doesn't yet have an analogue of Anka Controller for managing long living VMs. Please take a look at [CI integration](#ci-integration) section for an option to run ephemeral VMs for your needs.
Why Tart is free and open sourced? Apple did all the heavy lifting with their `Virtualization.Framework` and it just felt right to develop Tart in the open. Please consider [becoming a sponsor](https://github.com/sponsors/cirruslabs) if you find Tart saving a substantial amount of money on licensing and engineering hours for your company.
How to change VM's disk size? You can choose disk size upon creation of a virtual machine: ```shell tart create --from-ipsw=latest --disk-size=25 monterey-vanilla ``` For an existing VM please use [Packer Plugin](https://github.com/cirruslabs/packer-plugin-tart) which can increase disk size for new virtual machines. Here is an example of [how to change disk size in a Packer template](https://github.com/cirruslabs/macos-image-templates/blob/fb0bcf68e0b093129136875c050205a66729b596/templates/base.pkr.hcl#L15).
VM location on disk Tart stores all it's files in `~/.tart/` directory. Local images that you can run are stored in `~/.tart/vms/`. Remote images are pulled into `~/.tart/vms/cache/OCIs/`.
Nested virtualization support? Tart is limited by functionality of Apple's `Virtualization.Framework`. At the moment `Virtualization.Framework` doesn't support nested virtualization.
Changing the default NAT subnet To change the default network to `192.168.77.1`: ``` sudo defaults write /Library/Preferences/SystemConfiguration/com.apple.vmnet.plist Shared_Net_Address -string 192.168.77.1 ``` Note that even through a network would normally be specified as `192.168.77.0`, the [vmnet framework](https://developer.apple.com/documentation/vmnet) seems to treat this as a starting address too and refuses to pick up such network-like values. The default subnet mask `255.255.255.0` should suffice for most use-cases, however, you can also change it to `255.255.0.0`, for example: ``` sudo defaults write /Library/Preferences/SystemConfiguration/com.apple.vmnet.plist Shared_Net_Mask -string 255.255.0.0 ```