 *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 ```  ## 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 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