This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Examples

Running Linux commands

lima uname -a

Accessing host files

By default, the VM has read-only accesses to /Users/<USERNAME>.

To allow writing to /Users/<USERNAME>:

limactl edit --mount-writable

Running containers

nerdctl.lima run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine
limactl start template://docker
export DOCKER_HOST=$(limactl list docker --format 'unix://{{.Dir}}/sock/docker.sock')
docker run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine
limactl start template://podman
export DOCKER_HOST=$(limactl list podman --format 'unix://{{.Dir}}/sock/podman.sock')
docker run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine
limactl start template://k8s
export KUBECONFIG=$(limactl list k8s --format 'unix://{{.Dir}}/copied-from-guest/kubeconfig.yaml')
kubectl create deployment nginx --image nginx:alpine
kubectl create service nodeport nginx --node-port=31080 --tcp=80:80

Advanced configuration

limactl start \
  --name=default \
  --cpus=4 \
  --memory=8 \
  --vm-type=vz \
  --rosetta \
  --mount-writable \
  --network=vzNAT \
  template://fedora
  • --name=default: Set the instance name to “default”
  • --cpus=4: Set the number of the CPUs to 4
  • --memory=8: Set the amount of the memory to 8 GiB
  • --vm-type=vz: Use Apple’s Virtualization.framework (vz) to enable Rosetta, virtiofs, and vzNAT
  • --rosetta: Allow running Intel (AMD) binaries on ARM
  • --mount-writable: Make the home mount (/Users/<USERNAME>) writable
  • --network=vzNAT: Make the VM reachable from the host by its IP address
  • template://fedora: Use Fedora

1 - Containers

Lima was designed to facilitate running containers inside a virtual machine, with automatic filesystem sharing and port forwarding.

The original motivation of Lima was to promote containerd for macOS users, however, the current version of Lima supports other container engines too, and does not depend on macOS hosts.

1.1 - containerd (Default)

Lima comes with the built-in integration for containerd and nerdctl (contaiNERD CTL):

lima nerdctl run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine

or

nerdctl.lima run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine
  • If you have installed Lima by make install, the nerdctl.lima command is also available as nerdctl.
  • If you have installed Lima by brew install lima, you may make an alias (or a symlink) by yourself: alias nerdctl=nerdctl.lima
limactl start --containerd=system
lima sudo nerdctl run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine

The usage of the nerdctl command is similar to the docker command. See the Command Reference.

Disabling containerd

To disable containerd, start an instance with --containerd=none:

limactl start --containerd=none

1.1.1 - Advanced

1.1.1.1 - Enhanced supply chain security with gomodjail

gomodjail is an experimental library sandbox for Go modules.

gomodjail imposes syscall restrictions on a specific set of Go modules, so as to mitigate their potential vulnerabilities and supply chain attack vectors. A restricted module is hindered to access files and execute commands.

gomodjail can be enabled for nerdctl by using the nerdctl.gomodjail binary.

lima nerdctl.gomodjail ...

For the gomodjail policy applied to nerdctl.gomodjail, see https://github.com/containerd/nerdctl/blob/main/go.mod.

1.1.1.2 - Accelerating rootless networking with bypass4netns

bypass4netns is an experimental accelerator for rootless networking.

On macOS hosts, it is highly recommended to use the vzNAT networking in conjunction to reduce the overhead of Lima’s user-mode networking:

limactl start --network vzNAT

To enable bypass4netns, the daemon process (bypass4netnsd) has to be installed in the VM as follows:

lima containerd-rootless-setuptool.sh install-bypass4netnsd

Then run a container with an annotation nerdctl/bypass4netns=true:

# 192.168.64.1 is the IP address of the "bridge100" interface on the macOS host
lima nerdctl run --annotation nerdctl/bypass4netns=true alpine \
  sh -euc 'apk add iperf3 && iperf3 -c 192.168.64.1'

Benchmark result:

ModeThroughput
Rootless without bypass4netns2.30 Gbits/sec
Rootless with bypass4netns86.0 Gbits/sec
Rootful90.3 Gbits/sec
Benchmarking environment

  • Lima version: 2.0.0-alpha.2
    • nerdctl 2.1.6
    • containerd 2.1.4
    • bypass4netns 0.4.2
  • Container: Alpine Linux 3.22.2
    • iperf 3.19.1-r0 (apk)
  • Guest: Ubuntu 25.04
  • Host: macOS 26.0.1
    • iperf 3.19.1 (Homebrew)
  • Hardware: MacBook Pro 2024 (M4 Max, 128 GiB)

1.1.1.3 - Accelerating start-up time with eStargz

eStargz is an OCI-compatible container image format that reduces start-up latency using lazy-pulling technique.

The support for eStargz is available by default for ubuntu-24.04 instances:

limactl start --name=default template://ubuntu-24.04

The latest Ubuntu will be supported too in a future release.

Without eStargz:

$ time lima nerdctl run --platform=amd64 ghcr.io/stargz-containers/python:3.13-org python3 -c 'print("hi")'
[...]
hi

real	0m23.767s
user	0m0.025s
sys	0m0.020s

With eStargz:

$ time lima nerdctl --snapshotter=stargz run --platform=amd64 ghcr.io/stargz-containers/python:3.13-esgz python3 -c 'print("hi")'
[...]
hi

real	0m13.365s
user	0m0.026s
sys	0m0.021s

Examples of eStargz images can be found at https://github.com/containerd/stargz-snapshotter/blob/main/docs/pre-converted-images.md.

See also:

1.2 - Docker

limactl start template://docker
export DOCKER_HOST=$(limactl list docker --format 'unix://{{.Dir}}/sock/docker.sock')
docker run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine
limactl start template://docker-rootful
export DOCKER_HOST=$(limactl list docker-rootful --format 'unix://{{.Dir}}/sock/docker.sock')
docker run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine

1.3 - Podman

To use podman command in the VM:

limactl start template://podman
limactl shell podman podman run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine

To use podman command on the host:

export CONTAINER_HOST=$(limactl list podman --format 'unix://{{.Dir}}/sock/podman.sock')
podman --remote run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine

To use docker command on the host:

export DOCKER_HOST=$(limactl list podman --format 'unix://{{.Dir}}/sock/podman.sock')
docker run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine

To use podman command in the VM:

limactl start template://podman-rootful
limactl shell podman-rootful sudo podman run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine

To use podman command on the host:

export CONTAINER_HOST=$(limactl list podman-rootful --format 'unix://{{.Dir}}/sock/podman.sock')
podman --remote run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine

To use docker command on the host:

export DOCKER_HOST=$(limactl list podman-rootful --format 'unix://{{.Dir}}/sock/podman.sock')
docker run -d --name nginx -p 127.0.0.1:8080:80 docker.io/library/nginx:alpine

1.4 - Kubernetes

Single-node

limactl start template://k8s
export KUBECONFIG=$(limactl list k8s --format 'unix://{{.Dir}}/copied-from-guest/kubeconfig.yaml')
kubectl create deployment nginx --image nginx:alpine
kubectl create service nodeport nginx --node-port=31080 --tcp=80:80

Modify templates/k8s.yaml to change the kubeadm configuration.

See also https://kubernetes.io/docs/reference/setup-tools/kubeadm/.

limactl start template://k3s
export KUBECONFIG=$(limactl list k3s --format 'unix://{{.Dir}}/copied-from-guest/kubeconfig.yaml')
kubectl create deployment nginx --image nginx:alpine
kubectl create service nodeport nginx --node-port=31080 --tcp=80:80

See also https://docs.k3s.io.

limactl start template://k0s
export KUBECONFIG=$(limactl list k0s --format 'unix://{{.Dir}}/copied-from-guest/kubeconfig.yaml')
kubectl create deployment nginx --image nginx:alpine
kubectl create service nodeport nginx --node-port=31080 --tcp=80:80

See also https://docs.k0sproject.io/.

limactl start template://experimental/u7s
export KUBECONFIG=$(limactl list u7s --format 'unix://{{.Dir}}/copied-from-guest/kubeconfig.yaml')
kubectl create deployment nginx --image nginx:alpine
# NodePorts are not available by default in the case of Usernetes
kubectl port-forward deployments/nginx 8080:80

See also https://github.com/rootless-containers/usernetes.

Multi-node

A multi-node cluster can be created by creating multiple VMs connected via the (lima:user-v2 network.

limactl create --name k8s-0 --network lima:user-v2
limactl create --name k8s-1 --network lima:user-v2

The cluster has to be set up manually, as the built-in templates do not support multi-node mode yet. Support for multi-node template is tracked in https://github.com/lima-vm/lima/issues/4100.

1.5 - Apptainer

limactl start template://apptainer
limactl shell apptainer apptainer run -u -B $HOME:$HOME docker://alpine
limactl start template://apptainer-rootful
limactl shell apptainer-rootful apptainer run -u -B $HOME:$HOME docker://alpine

See also https://apptainer.org/docs/user/latest/.

2 - AI agents

Lima is useful for running AI agents inside a VM, so as to prevent agents from directly reading, writing, or executing the host files.

For running AI agents, it is highly recommended to only mount your project directory (current directory) into the VM:

limactl start --mount-only .:w

Drop :w for read-only mode.

limactl start --set ".mounts=[{\"location\":\"$(pwd)\", \"writable\":true}]"

Set writable to false for read-only mode.

lima sudo apt install -y pipx
lima pipx install aider-install
lima sh -c 'echo "export PATH=$PATH:$HOME/.local/bin" >>~/.bash_profile'
lima aider-install
lima aider

Follow the guide shown in the first session for authentication.

Alternatively, you can set environmental variables via:

lima vi "/home/${USER}.linux/.bash_profile"

See also https://github.com/Aider-AI/aider.

lima sudo snap install node --classic
lima sudo npm install -g @anthropic-ai/claude-code
lima claude

Follow the guide shown in the first session for authentication.

Alternatively, you can set export ANTHROPIC_API_KEY... via:

lima vi "/home/${USER}.linux/.bash_profile"

See also https://github.com/anthropics/claude-code.

lima sudo snap install node --classic
lima sudo npm install -g @openai/codex
lima codex

Follow the guide shown in the first session for authentication.

Alternatively, you can set export OPENAI_API_KEY... via:

lima vi "/home/${USER}.linux/.bash_profile"

See also https://github.com/openai/codex.

lima sudo snap install node --classic
lima sudo npm install -g @google/gemini-cli
lima gemini

Follow the guide shown in the first session for authentication.

Alternatively, you can set export GEMINI_API_KEY... via:

lima vi "/home/${USER}.linux/.bash_profile"

See also https://github.com/google-gemini/gemini-cli.

lima sudo snap install node --classic
lima sudo npm install -g @github/copilot
lima copilot

Type /login in the first session for authentication.

Alternatively, you can set export GH_TOKEN=... via:

lima vi "/home/${USER}.linux/.bash_profile"

See also https://github.com/github/copilot-cli.

See also

3 - Visual Studio Code

Securing Visual Studio Code with Lima

Lima helps securing the development environment by running it inside a VM. Notably, this prevents AI agents, such as GitHub Copilot in VS Code, from directly executing untrusted commands on the host.

  1. Start a Lima instance. If you use GitHub Copilot, consider disabling mounts by passing the --mount-none flag to prevent Copilot from accessing host files:
limactl start --mount-none
  1. Add the following line to ~/.ssh/config:
Include ~/.lima/*/ssh.config
  1. Open the Remote Explorer in the Visual Studio Code sidebar and select lima-<INSTANCE> from the SSH remote list.

  1. Set up the workspace by clicking Clone Git Repository... on the Welcome screen, or copy the project directory with limactl cp:
limactl cp -r DIR default:~/

4 - GitHub Actions

Running Lima on GitHub Actions

On GitHub Actions, Lima is useful for:

  • Running commands on non-Ubuntu operating systems (e.g., Fedora for testing SELinux)
  • Emulating multiple hosts

While these tasks can be partially accomplished with containers like Docker, those containers still rely on the Ubuntu host’s kernel and cannot utilize features missing in Ubuntu, such as SELinux.

In contrast, Lima runs virtual machines that do not depend on the Ubuntu host’s kernel.

The following GitHub Actions workflow illustrates how to run multiple instances of Fedora using Lima. The instances are connected by the user-v2 network.

name: Fedora

on:
  workflow_dispatch:
  pull_request:

jobs:
  fedora:
    runs-on: ubuntu-24.04
    steps:
    - name: Check out code
      uses: actions/checkout@v4

    - name: "Set up Lima"
      uses: lima-vm/lima-actions/setup@v1
      id: lima-actions-setup

    - name: "Cache ~/.cache/lima"
      uses: actions/cache@v4
      with:
        path: ~/.cache/lima
        key: lima-${{ steps.lima-actions-setup.outputs.version }}

    - name: "Start an instance of Fedora"
      run: |
        set -eux
        limactl start --name=default --cpus=1 --memory=1 --network=lima:user-v2 template://fedora
        lima sudo dnf install -y httpd
        lima sudo systemctl enable --now httpd        

    - name: "Start another instance of Fedora"
      run: |
        set -eux
        limactl start --name=another --cpus=1 --memory=1 --network=lima:user-v2 template://fedora
        limactl shell another curl http://lima-default.internal        

See also https://github.com/lima-vm/lima-actions.

Plain mode

The --plain mode is useful when you want the VM instance to be as close as possible to a physical host:

    - name: "Start Fedora"
      # --plain is set to disable file sharing, port forwarding, built-in containerd, etc.
      run: limactl start --plain --name=default --cpus=1 --memory=1 --network=lima:user-v2 template://fedora

    - name: "Set up SSH"
      uses: lima-vm/lima-actions/ssh@v1

    - name: "Initialize Fedora"
      # plain old rsync and ssh are used for the initialization of the guest,
      # so that people who are not familiar with Lima can understand the initialization steps.
      run: |
        set -eux -o pipefail
        # Sync the current directory to /tmp/repo in the guest
        rsync -a -e ssh . lima-default:/tmp/repo
        # Install packages
        ssh lima-default sudo dnf install -y httpd        

Full examples

Kubernetes:

Container engines:

Container runtimes:

Others: