Lima
Lima launches Linux virtual machines on macOS (and Linux, NetBSD and Windows hosts) with automatic file sharing and port forwarding, driven by a YAML template and the limactl CLI. On a modern Mac it uses Apple's Virtualization framework (vmType vz); cloud-init provisions the guest and a guest agent reports listening ports so the host agent can forward them. Apache 2.0, free, and a CNCF incubating project; the current stable line is 2.2 (2.2.1). It fits when a Mac has to host real Linux VMs, for example K3s nodes, without Docker Desktop or a paid VM manager.
Lima is a command-line VM manager that runs Linux guests on a Mac, with file sharing and port forwarding set up automatically, in the way WSL2 does on Windows. It started as a way to bring containerd and nerdctl to macOS users. It now also serves as the VM layer under Rancher Desktop, Colima, Finch and the Podman Desktop Lima plug-in, and it can host Kubernetes nodes directly. The official docs at lima-vm.io/docs own the full YAML reference.
What it is
One Go binary pair (limactl and the lima shell wrapper) plus a guest agent that Lima injects into each VM. Every VM ("instance") is defined by a YAML template. Templates can inherit from other templates through base:, so a shared base file and a small per-VM file are the normal way to keep a fleet of VMs consistent.
- Licence: Apache 2.0.
- Governance: a Cloud Native Computing Foundation incubating project. Lima 2.0 marked the promotion from Sandbox to Incubating.
- Current release line: 2.2, with v2.2.1 released 2026-10-03 (bug fixes, nerdctl 2.4.1, a
macos-27template). A 2.3 beta line is open (v2.3.0-beta.1 on the same day). The 2.3 builds add CycloneDX SBOMs to the downloads. - VM drivers:
vz(Apple Virtualization framework, the default on macOS 13.5 and later),qemu(the default elsewhere, and the default on Windows hosts since 2.2),wsl2, and an experimentalkrunkitdriver for GPU acceleration. Lima 2.0 added a plug-in system for third-party drivers. - Guests: Linux distributions from the template catalogue (Ubuntu, Debian, Fedora, Alpine and others). Lima 2.2 adds experimental Windows 11 and Windows Server 2025 guests, and macOS guests are possible on Apple silicon.
Recent changes worth knowing:
| Release | Change |
|---|---|
| 2.0 | Pluggable VM drivers, krunkit (GPU), MCP sandbox tools. /tmp/lima no longer mounted by default. UDP ports forwarded by default. Relative paths in YAML prohibited. template:default replaces template://default. SSH over AF_VSOCK for vz guests. |
| 2.1 | basedisk and diffdisk merged into one disk file per instance. limactl shell --sync. |
| 2.2 | Experimental Windows guests, opt-out of password-less sudo, LaunchDaemon support for headless Macs, limactl screenshot, k8s template takes version and registry parameters. socket_vmnet access limited to the admin group. |
How it works
limactl start reads the instance's lima.yaml, builds a cloud-init ISO, and starts a per-instance host agent process on the Mac. The host agent boots the VM through the chosen driver and keeps running for the VM's lifetime. Inside the guest, cloud-init's NoCloud datasource reads the cidata ISO, creates the user, installs the SSH key, runs Lima's boot scripts and then the template's provision scripts. A readiness probe in the template can hold limactl start until a condition is true, for example a kubeconfig file existing.
The instance directory under ~/.lima/<name>/ is the state on disk: lima.yaml, disk, cidata.iso, ha.sock (the host agent's REST API), ha.stdout.log / ha.stderr.log, ssh.sock and, for vz, vz.pid. The guest agent talks to the host agent over vsock port 2222 on vz and over a virtio port on QEMU.
Step 1 of 6. limactl start <name> loads lima.yaml and resolves every base: template into one merged configuration.
vz driver on macOS with the default gRPC port forwarder.
Networking has three layers, and they combine:
- Default user-mode network. NAT out to the internet, no inbound path. The Mac reaches services only through port forwards.
vzNAT(vz only, macOS 13+). Gives the guest an address the Mac can reach directly. Needs nosocket_vmnetand no sudoers file. Other guests cannot reach it.user-v2. A user-mode network shared between instances, so VMs reach each other by name aslima-<name>.internal. Those names resolve inside guests only. Enablinguser-v2replaces the default user-mode network on that instance.
When to use it
Reach for it when:
- A Mac has to run real Linux VMs (systemd, a full kernel, your own init) and not only containers.
- You want K3s or kubeadm nodes on a laptop or a Mac mini, with several VMs that talk to each other.
- You want VM definitions as code: YAML templates in Git,
base:inheritance, provision scripts and readiness probes. - You want a free, open-source alternative to Docker Desktop's VM. Colima and Rancher Desktop already use Lima under the hood.
- You need a sandbox VM for AI agents, using
limactl shell --syncor the MCP tools.
Skip it when:
- You only need
docker runon a Mac. Colima or Rancher Desktop wrap Lima with less configuration. - You want a GUI to create and watch VMs. UTM gives that on top of the same hypervisors.
- The VMs must run on several physical hosts or need live migration. That is a hypervisor cluster's job.
- You need VMs that the rest of the LAN reaches as first-class hosts and you will not set up
socket_vmnetbridged mode.
At a glance
Core concepts
- Instance — one VM, named, with its own directory, disk and host agent.
- Template — YAML that defines an instance.
template:<name>refers to the built-in catalogue.base:chains templates; the instance file overrides the base. - Provision scripts —
system,user,bootanddependencymodes. They run on every boot, so they must be idempotent. - Probes —
readinessscripts that holdlimactl startuntil they pass. portForwards— ordered rules. First match wins. An internal fallback rule at the end forwards any guest port on127.0.0.1or0.0.0.0to the same port on the Mac's127.0.0.1.copyToHost— files copied out after provisioning, for example a kubeconfig, optionally deleted on stop.- Plain mode —
--plainturns off mounts, port forwarding and the guest agent; onlystatic: trueforwards apply.
Key facts
| Item | Value |
|---|---|
| Default vmType on macOS | vz on 13.5 and later, qemu before |
| Default CPUs / memory / disk | min(4, host cores) / min(4 GiB, half of host RAM) / 100 GiB |
| Default mounts | Home directory, read-only |
| Default mount type | virtiofs on vz, 9p on QEMU |
| Port forwarder | gRPC by default since 1.1; SSH forwarder by LIMA_SSH_PORT_FORWARDER=true (no UDP) |
| Autostart | limactl autostart enable <name> (launchd on macOS); start-at-login is deprecated |
| vmType after create | Fixed. A different driver means a new instance. |
Lima vs other Mac VM managers
| Aspect | Lima | Multipass | UTM |
|---|---|---|---|
| Interface | CLI + YAML templates | CLI + cloud-init | GUI |
| Guests | Many Linux distros, macOS, experimental Windows | Ubuntu | Any QEMU or Apple guest |
| Automatic port forwards | Yes, rule-driven | No | No |
| Licence | Apache 2.0 | GPLv3 | Apache 2.0 |
How to integrate
Install and start a default Ubuntu VM:
brew install lima
limactl start # creates and boots the "default" instance
lima uname -a # run a command in it
limactl list # name, status, SSH port, vmType, CPUs, memory, disk
A shared base and a thin per-VM template, with VM-to-VM and Mac-to-VM networking, explicit forwards and a pinned K3s:
# base.yaml
minimumLimaVersion: 2.0.0
vmType: vz
base: template:_images/ubuntu-lts
mounts: []
containerd: {system: false, user: false} # K3s brings its own containerd
networks:
- vzNAT: true # the Mac can reach the VM's address
- lima: user-v2 # VMs resolve each other as lima-<name>.internal
provision:
- mode: system
script: |
#!/bin/sh
set -eu
if [ ! -d /var/lib/rancher/k3s ]; then
curl -sfL https://get.k3s.io | \
INSTALL_K3S_VERSION="{{.Param.k3sVersion}}" \
INSTALL_K3S_EXEC="server --write-kubeconfig-mode 644" sh -
fi
probes:
- script: |
#!/bin/bash
timeout 60s bash -c "until test -f /etc/rancher/k3s/k3s.yaml; do sleep 3; done"
copyToHost:
- guest: /etc/rancher/k3s/k3s.yaml
host: "{{.Dir}}/copied-from-guest/kubeconfig.yaml"
deleteOnStop: true
# node-a.yaml
base: ./base.yaml # resolved next to this file
cpus: 6
memory: 16GiB
param:
k3sVersion: v1.34.1+k3s1 # pin; example value
portForwards:
- guestPort: 6443 # this VM's API server
hostPort: 16443 # a unique Mac port per VM
- guestIP: 0.0.0.0 # everything else stays inside the VM
proto: any
ignore: true
limactl start --name node-a ./node-a.yaml
export KUBECONFIG=$(limactl list node-a --format '{{.Dir}}/copied-from-guest/kubeconfig.yaml')
# The copied kubeconfig points at 127.0.0.1:6443; change the port to 16443.
limactl autostart enable node-a # boot at login via launchd
limactl edit node-a # changes apply on the next start
limactl stop node-a && limactl start node-a
In the GL stack
Lima 2.2.1 is the VM layer under the whole homelab. It runs on one Mac with the Apple Virtualization framework (vz) and hosts three Ubuntu 26.04 VMs, one per K3s cluster: management (8 CPU, 24 GiB), beta (6 CPU, 16 GiB) and prod (8 CPU, 36 GiB). The prod VM carries the shared data services that back paiddaily.io, sagedaily.io and the other products.
Each VM has two networks. vzNAT lets the Mac reach the VM. user-v2 lets the VMs reach each other by their Lima names, which is how the management cluster talks to the beta and prod clusters. Nothing reaches the Mac by accident: each template lists its port forwards explicitly and ends with catch-all ignore rules, so a new service in a VM stays private until a forward is added for it. Adding a forward is a template change plus a VM restart (limactl stop, then limactl start), because the host agent reads the rules only at start.
The VM templates are code: one shared base file with the image, networks and provisioning, and one small file per VM with its size and forwards. The base template's provision script installs K3s at a pinned version, so a rebuilt VM comes back on the same Kubernetes release. launchd starts all three VMs at login, so the clusters come up without a manual step after a reboot.
Gotchas
- Two VMs, one host port. The fallback rule forwards every guest port to the same port on the Mac's
127.0.0.1. Two K3s VMs both listen on 6443, so the second forward fails. Map ports explicitly and end the list with anignorerule. - Rule order matters. Rules are checked top to bottom and the first match wins. An
ignorerule placed above a forward hides the forward. - Config changes need a restart.
limactl editwriteslima.yaml; CPUs, memory, mounts, networks and port forwards apply on the nextlimactl start. - vmType is fixed at create time. Moving an instance from
qemutovzmeans a new instance and a data migration. lima-<name>.internaldoes not resolve on the Mac. It works inside guests only. From the Mac, usevzNATaddresses, port forwards or the experimentallimactl tunnelSOCKS proxy.user-v2replaces the default user-mode network on the instances that use it. Test outbound access after adding it.- Provision scripts run on every boot. Guard installers (
if [ ! -d /var/lib/rancher/k3s ]), or a reboot reinstalls or upgrades. - Pre-2.1 instances keep the old
basedisk/diffdisklayout. Backup scripts that copy disk files by name must handle both. - Home is mounted read-only by default, and
/tmp/limais no longer mounted since 2.0. Setmounts: []for server VMs that need no host files. start-at-loginis deprecated in favour oflimactl autostart. Scripts that call the old command print a warning.
Risks
- Project health. CNCF incubating, Apache 2.0, a steady cadence of minor releases with patch releases between them, and several downstream products (Rancher Desktop, Colima, Finch) that depend on it. Low risk of abandonment.
- Single-host failure domain. Every VM shares one Mac's power, disk and macOS updates. A macOS upgrade or a full disk stops every cluster at once. Back up the cluster data off the host.
- Experimental features. Windows guests, krunkit, MCP,
limactl tunneland the driver plug-in system are marked experimental. Keep production VMs onvzwith stable options. - Security. Guests get password-less sudo by default, and the home directory is mounted unless turned off. Forwards bind to
127.0.0.1unless a rule setshostIP: 0.0.0.0, which exposes the port to the network.socket_vmnetmust be installed root-owned; Homebrew installs of it are rejected. - Lock-in. Low. The guests are standard cloud images, and the YAML is the only Lima-specific artefact.
Alternatives
- Colima — Docker or containerd on a Mac with almost no configuration. Built on Lima. Pick it when the goal is containers, not VMs.
- Multipass — Canonical's Ubuntu VM manager. Pick it when every guest is Ubuntu and a simple CLI is enough.
- UTM — a GUI over QEMU and Apple virtualization. Pick it for desktop guests and interactive VM work.
- Rancher Desktop — a desktop app with Kubernetes (K3s) and a container engine, on Lima. Pick it for a single local dev cluster with a GUI.
Related
- K3s — the Kubernetes distribution the VMs run.
- Rancher — the management plane over the three clusters.
- Fleet and Argo CD — what deploys into the clusters.
- Velero — cluster backups off the single host.
- Lima documentation
- Lima releases
- Network configuration
- Port forwarding
