Lima enables you to run a Linux machine on your Mac for free. This tutorial helps you install Lima, launch a Linux VM, verify shared files, and run a web server in a container accessible via your browser.

If you want the concepts first, read What Is Lima? and come back. This article stays hands-on.

What You’ll Build

A working Lima setup: an Ubuntu virtual machine (VM) running on your Mac, managed from your terminal, serving a containerized nginx web page at localhost:8080.

What success looks like: you type curl localhost:8080 on your Mac and get a “Welcome to nginx!” page served from Linux.

What You’ll Learn

  • How to install Lima and start your first Linux VM.
  • How to run Linux commands from your Mac terminal.
  • How file sharing between your Mac and the VM works.
  • How to run a container with nerdctl and reach it from your Mac.

Time estimate: about 30 minutes, mostly waiting for downloads. Difficulty: beginner.

Prerequisites

You need:

  • A Mac with Homebrew installed. Apple Silicon or Intel both work.
  • macOS 13 or newer. Lima’s fast vz driver needs it. Older macOS versions fall back to the slower QEMU driver.
  • About 5 GB of free disk space for the VM image and container images.
  • A terminal you’re comfortable with.

This tutorial covers Lima 2.x on Apple Silicon, verified against Lima 2.2. The commands have been stable since Lima 1.0, but the defaults behind them have not: Lima 2.0 stopped mounting /tmp/lima by default and renamed template locators, so steps written for Lima 1.x can fail on 2.x. Step 1 asks for that mount explicitly, which works on both.

You don’t need:

  • Docker, Docker Desktop, or any container experience.
  • Any virtualization knowledge. Lima handles the VM plumbing.

Everything in this tutorial is reversible; one command at the end removes the VM and all contents.

Setup

Install Lima

Install Lima with Homebrew:

brew install lima

Confirm it installed:

limactl --version

You should see: a version string such as limactl version 2.2.2. Your version number will differ, and that’s fine.

Checkpoint: If limactl prints a version, you’re ready. If your shell says command not found, jump to Troubleshooting.

Tutorial Steps

Step 1: Start your first Linux VM

Lima calls each VM an instance. Start the default one:

limactl start --containerd user --mount '/tmp/lima:w'

Both flags matter:

  • --containerd user asks for user-mode containerd, the container engine behind Step 4, along with the nerdctl command. Lima 2.x enables it by default for Linux guests, so the flag is insurance: it keeps this tutorial working on older Lima versions and if the default changes again. Run limactl info and look at defaultTemplate.containerd to see what your version does.
  • --mount '/tmp/lima:w' shares /tmp/lima between your Mac and the VM, and the :w suffix makes it writable. Lima 2.0 stopped mounting that directory by default, and Step 3 uses it. Lima creates the directory on your Mac if it isn’t there yet.

On the first run, it asks how to create the instance. Pick Proceed with the current configuration and press Enter. The defaults give you an Ubuntu VM with 4 CPUs, 4 GiB of memory, and a 100 GiB disk that uses space only as needed.

The first start downloads an Ubuntu image, so give it a few minutes.

You should see: log lines about downloading and booting, ending with:

READY. Run `lima` to open the shell.

What just happened: Lima downloaded Ubuntu, created a VM named default, booted it, and wired up file sharing and port forwarding. You now have a Linux kernel running on your Mac.

Checkpoint: Run limactl list. The default instance shows Running in the STATUS column:

NAME       STATUS     SSH                VMTYPE    ARCH       CPUS    MEMORY    DISK      DIR
default    Running    127.0.0.1:60022    vz        aarch64    4       4GiB      100GiB    ~/.lima/default

Your SSH port and architecture may differ. Running is what matters.

Step 2: Run Linux commands from your Mac

The lima command runs whatever you give it inside the VM. Prove you’re talking to Linux:

lima uname -a

You should see: a line starting with Linux lima-default, ending in aarch64 GNU/Linux on Apple Silicon or x86_64 GNU/Linux on Intel.

Your Mac would have said Darwin. This output comes from the Ubuntu kernel inside the VM.

Run lima with no arguments to open an interactive shell in the VM, then exit to come back to macOS. For the rest of this tutorial, stay on the Mac side and prefix commands with lima.

Checkpoint: lima whoami prints your macOS username. Lima creates a matching user inside the guest so file permissions line up.

Step 3: See file sharing in action

Your instance has two shares. /tmp/lima is writable in both directions, thanks to the --mount '/tmp/lima:w' flag from Step 1. Your Mac home directory is mounted at the same path inside the guest, but read-only. Test both.

Create a file on your Mac:

echo "hello from macOS" > /tmp/lima/from-mac.txt

Read it from inside Linux:

lima cat /tmp/lima/from-mac.txt

You should see: hello from macOS.

Now go the other way. Write a file from the Linux side:

lima sh -c 'echo "hello from Linux" > /tmp/lima/from-linux.txt'

Read it on your Mac, with no lima prefix this time:

cat /tmp/lima/from-linux.txt

You should see: hello from Linux.

Now confirm the other share is read-only:

lima sh -c "echo nope > $HOME/should-fail.txt"

You should see: an error ending in Read-only file system.

What just happened: both systems see the same files under /tmp/lima with no copying or syncing. Your home directory also appears inside the guest so you can read your projects, but the read-only mount keeps a misbehaving VM from writing to your Mac.

Watch which shell expands your paths. $HOME above expands on your Mac before the command reaches the VM, which is why it lands on the mounted /Users/you. Inside the guest, ~ is the VM’s own home at /home/you.linux, which is writable and invisible to your Mac, so it is the wrong place for files you want to share.

Checkpoint: If both reads worked and the home write was refused, file sharing is healthy. Clean up the test files:

rm /tmp/lima/from-mac.txt /tmp/lima/from-linux.txt

Step 4: Run a container and reach it from your Mac

The --containerd user flag from Step 1 gave your instance containerd and nerdctl, a command that works like docker. Start an nginx web server:

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

You should see: image download progress, then a long container ID on the last line.

Now ask for the page from your Mac:

curl localhost:8080

You should see: HTML containing Welcome to nginx!. Opening http://localhost:8080 in your browser shows the same page.

What just happened: The container runs inside the VM and listens on the VM’s port 8080. Lima noticed the port binding and forwarded it to your Mac automatically, so localhost works as if the server were native.

Checkpoint: lima nerdctl ps lists the web container with a status of Up.

Verification

You’re done when all three are true:

  • limactl list shows the default instance as Running.
  • lima uname prints Linux.
  • curl localhost:8080 returns the nginx welcome page.

Then clean up the tutorial container:

lima nerdctl rm -f web

When you’re not using the VM, stop it to free memory:

limactl stop

Start it again anytime with limactl start. Your VM and its contents survive stops. To remove Lima entirely, limactl delete default deletes the VM and brew uninstall lima removes the tool.

Troubleshooting

Problem: limactl: command not found.

Symptoms: The shell can’t find limactl right after installing.

Solution: Your shell hasn’t picked up Homebrew’s path. Run eval "$(brew shellenv)" or open a new terminal window.

If that doesn’t work: run brew list lima to confirm the install succeeded, then brew doctor to check your Homebrew setup.

Problem: the first start hangs or takes forever

Symptoms: limactl start sits on a download for many minutes.

Solution: The first start pulls an Ubuntu image of several hundred megabytes. On slow connections, this takes a while, and later starts skip the download. Let it finish.

If that doesn’t work: press Ctrl+C, then run limactl start again. Downloads resume from cache, and a corrupted download restarts cleanly.

Problem: Read-only file system when writing a file

Symptoms: writing anywhere under your Mac home directory from inside the VM fails.

Solution: That’s by design, as Step 3 shows. Your home directory mounts read-only for safety. Write to /tmp/lima instead, which is shared in both directions.

If that doesn’t work: /tmp/lima is read-only too, or missing, when the instance was created before Lima 2.0 dropped that mount or without the --mount flag from Step 1. Add it to an existing instance:

limactl stop
limactl edit default --set '.mounts += [{"location": "/tmp/lima", "writable": true}]'
limactl start

Confirm it took with lima mount | grep /tmp/lima, which should report rw.

Problem: nerdctl: command not found

Symptoms: Step 4 fails with /bin/bash: line 1: nerdctl: command not found.

Solution: The instance was created without containerd. Lima 2.x enables it by default, so this points at an instance created by an older Lima or from a template that turns it off. Enable it on the existing instance:

limactl stop
limactl edit default --set '.containerd.user=true'
limactl start

Lima installs nerdctl inside the VM on the next start. Rerun Step 4 afterward.

If that doesn’t work: run grep -A2 '^containerd:' ~/.lima/default/lima.yaml on your Mac. If user still shows false, the edit didn’t save; rerun the limactl edit command.

Problem: port 8080 is already taken

Symptoms: the container starts, but curl localhost:8080 returns something that isn’t nginx, or the run command fails to bind.

Solution: Another app on your Mac owns 8080. Remove the container with lima nerdctl rm -f web, then rerun Step 4 with -p 8081:80 and curl localhost:8081.

If that doesn’t work: lsof -i :8080 on your Mac shows which process holds the port.

Next Steps

To learn more:

  • Read What Is Lima? for the mental model behind what you just built: the hypervisor, the mounts, and the port forwarder.
  • Browse the Lima documentation for configuration, templates, and drivers.

To extend this project:

  • Try another template: limactl start --name=docker template:docker gives you a VM with a real Docker daemon, so the docker command works against it. Lima 2.0 renamed the older template://docker form, which still works but warns.
  • Give the VM more or less hardware with limactl edit default, which opens the instance’s YAML configuration.
  • If you want a drop-in docker replacement with one command, look at Colima, which builds on Lima.

References

  • Lima documentation, the official guide covering installation, templates, mounts, and port forwarding.
  • Homebrew, the macOS package manager used to install Lima.
  • Colima, a Lima-based tool that provides a Docker-compatible runtime.