|
1 | 1 | --- |
2 | | -title: 📈 ArchLinux Meets Lima |
3 | | -summary: Run ArchLinux virtual Machine on MacOS using Lima |
4 | | -date: 2023-10-23 |
5 | | -draft: true |
| 2 | +title: 📈 Run an ArchLinux sandbox with Lima on MacOS |
| 3 | +summary: This post explores how to run virtual machine work loads on MacOS efficiently with latest open-source virtualization software Lima. |
| 4 | +date: 2025-07-02 |
6 | 5 | authors: |
7 | 6 | - admin |
8 | 7 | tags: |
9 | | - - ArchLinux |
10 | 8 | - Lima |
| 9 | + - ArchLinux |
11 | 10 | - Virtual Machine |
12 | | -image: |
13 | | - caption: 'Image credit: [**ArchLinux**](https://bbs.archlinux.org/viewtopic.php?id=259604)' |
14 | 11 | --- |
15 | 12 |
|
16 | | -TODO: coming soon ... |
| 13 | +## Background |
| 14 | + |
| 15 | +MacBook is solid. Recently, I sold a ten years old 2013 MBP which works |
| 16 | +smoothly without any glitch. I believe this is why MacBook laptops are a go-to |
| 17 | +choice among developers: according to the [2024 Stack Overflow Developer |
| 18 | +Survey](https://www.linkedin.com/pulse/why-software-developers-choose-macbooks-dimitar-stojkoski-d1nyf?utm_source=chatgpt.com), |
| 19 | +**30.65% of professional developers report using macOS**. |
| 20 | + |
| 21 | +Although being a firm MacBook supporter, I still need tinker with various Linux |
| 22 | +distros from time to time. However, dual-boot with Linux is not particularly |
| 23 | +feasible as 1) switching to Linux requires reboot, 2) Linux support of apple |
| 24 | +hardware is problematic for quite a few Linux distros. This leads to the |
| 25 | +virtualization solutions like Parallels, VMware. However, paying a hefty price |
| 26 | +for occasional use is far from wise. Enters Lima. |
| 27 | + |
| 28 | +## Overview |
| 29 | + |
| 30 | +[Lima](https://github.com/lima-vm/lima) (short for *Linux Machines*) is a |
| 31 | +lightweight virtual machine manager that enables you to run Linux virtual |
| 32 | +machines on macOS with ease. It's designed to provide a developer-friendly |
| 33 | +environment for container tooling, testing, and Linux workflows directly from |
| 34 | +your macOS terminal. There are plenty of benefits of Lima, for example: |
| 35 | + |
| 36 | +- Runs Linux VMs efficiently and seamlessly on macOS |
| 37 | +- Easy provisioning with declarative YAML files |
| 38 | +- Shares host file system and port forwarding |
| 39 | +- Integrated with Docker and nerdctl |
| 40 | + |
| 41 | +With Lima, we can |
| 42 | + |
| 43 | +- Experiment with different Linux distributions in isolated environments |
| 44 | +- Run container workloads with rootless Docker/nerdctl |
| 45 | +- Develop cross-platform software |
| 46 | +- Sandbox for package and software testing |
| 47 | + |
| 48 | +Lima's declarative way to describe the virtual machine to build obviates the |
| 49 | +need of dedicated tools like vagrant, or custom shell script. In this post, |
| 50 | +I'll take advantage of this feature to build a recent ArchLinux with capability |
| 51 | +to run GUI application, fast mirror for software download, enable AUR and yay |
| 52 | +to install latest software conveniently. |
| 53 | + |
| 54 | +## Define the ArchLinux VM |
| 55 | + |
| 56 | +A LimaVM instance can be defined declaratively with a YAML configuration file. |
| 57 | +To build the proposed ArchLinux VM, we need customize the YAML as follows: |
| 58 | + |
| 59 | +- Specify CPU cores, memory capacity |
| 60 | +- Specify the pre-built cloud image of ArchLinux |
| 61 | +- Set fast mirror using system provision script |
| 62 | +- Setup SSH and XWindow display using user provision script |
| 63 | +- Setup AUR and yay using user provision script |
| 64 | + |
| 65 | +Here’s the complete YAML for the ArchLinux VM to build: |
| 66 | + |
| 67 | +```yaml |
| 68 | + |
| 69 | +minimumLimaVersion: 1.1.0 |
| 70 | + |
| 71 | +cpus: 6 |
| 72 | +memory: 8GiB |
| 73 | +mountType: virtiofs |
| 74 | +networks: |
| 75 | + - vzNAT: true |
| 76 | +rosetta: |
| 77 | + enabled: true |
| 78 | + binfmt: true |
| 79 | +vmType: vz |
| 80 | +base: |
| 81 | + - template://_default/mounts |
| 82 | +images: |
| 83 | + - location: "https://geo.mirror.pkgbuild.com/images/v20250615.366044/Arch-Linux-x86_64-cloudimg-20250615.366044.qcow2" |
| 84 | + arch: "x86_64" |
| 85 | + digest: "sha256:a8fb36fd4a60ac606c99efd01f5ef959612d11748e8b686001b37e29411b00a4" |
| 86 | + |
| 87 | + # Fallback to the latest release image. |
| 88 | + # Hint: run `limactl prune` to invalidate the cache |
| 89 | + - location: https://geo.mirror.pkgbuild.com/images/latest/Arch-Linux-x86_64-cloudimg.qcow2 |
| 90 | + arch: x86_64 |
| 91 | +provision: |
| 92 | + - mode: system |
| 93 | + script: | |
| 94 | + #!/bin/bash |
| 95 | + set -eux -o pipefail |
| 96 | + # Use New Zealand mirrors |
| 97 | + cat<<'EOF' > /etc/pacman.d/mirrorlist |
| 98 | +
|
| 99 | + # New Zealand |
| 100 | + Server = https://mirror.fsmg.org.nz/archlinux/$repo/os/$arch |
| 101 | + Server = https://archlinux.ourhome.kiwi/$repo/os/$arch |
| 102 | + Server = https://nz.arch.niranjan.co/$repo/os/$arch |
| 103 | + Server = https://mirror.2degrees.nz/archlinux/$repo/os/$arch |
| 104 | + EOF |
| 105 | + pacman -Syyu --noconfirm --needed base-devel git |
| 106 | + # Install yay as normal user |
| 107 | + - mode: user |
| 108 | + script: | |
| 109 | + #!/bin/bash |
| 110 | + set -eux -o pipefail |
| 111 | + cd /tmp && \ |
| 112 | + git clone https://aur.archlinux.org/yay.git && \ |
| 113 | + cd yay && \ |
| 114 | + makepkg --noconfirm -si && \ |
| 115 | + cd && \ |
| 116 | + rm -fr /tmp/yay |
| 117 | + # Setup XWindow and SSH |
| 118 | + - mode: user |
| 119 | + script: | |
| 120 | + #!/bin/bash |
| 121 | + set -eux -o pipefail |
| 122 | + if ! grep "User git" ~/.ssh/config; then |
| 123 | + HOST_USER=$(ls /Users) |
| 124 | + cat<<EOF >> ~/.ssh/config |
| 125 | + Host github.com |
| 126 | + User git |
| 127 | + Port 22 |
| 128 | + StrictHostKeyChecking no |
| 129 | + PasswordAuthentication no |
| 130 | + IdentityFile /Users/$HOST_USER/.ssh/id_ed25519 |
| 131 | + EOF |
| 132 | + fi |
| 133 | +
|
| 134 | + if ! grep -e "^export DISPLAY=host.lima.internal:0" ~/.bashrc; then |
| 135 | + echo "export DISPLAY=host.lima.internal:0" >> ~/.bashrc |
| 136 | + fi |
| 137 | +``` |
| 138 | +
|
| 139 | +
|
| 140 | +### Define the VM |
| 141 | +
|
| 142 | +The key parameters to define a VM include: |
| 143 | +
|
| 144 | +- **`cpus`**: Allocate CPU cores for the VM. |
| 145 | +- **`memory`**: Allocate memory for the VM. |
| 146 | +- **`images`**: Cloud image used to boot ArchLinux. The example YAML uses a recent ArchLinux cloud image |
| 147 | + |
| 148 | +<!-- - **`provision`**: Scripts run automatically after the VM is created, used to set up fast mirrors, install AUR helper, and configure GUI support. --> |
| 149 | +<!----> |
| 150 | + |
| 151 | +### Enable Fast Mirrors |
| 152 | + |
| 153 | +ArchLinux has plenty of mirrors to accelerate software download globally. The |
| 154 | +first system provision script in the example YAML: specifies the mirrors like |
| 155 | +explicitly as follows: |
| 156 | + |
| 157 | +```sh |
| 158 | +# Use New Zealand mirrors |
| 159 | +cat<<'EOF' > /etc/pacman.d/mirrorlist |
| 160 | +
|
| 161 | +# New Zealand |
| 162 | +Server = https://mirror.fsmg.org.nz/archlinux/$repo/os/$arch |
| 163 | +Server = https://archlinux.ourhome.kiwi/$repo/os/$arch |
| 164 | +Server = https://nz.arch.niranjan.co/$repo/os/$arch |
| 165 | +Server = https://mirror.2degrees.nz/archlinux/$repo/os/$arch |
| 166 | +EOF |
| 167 | +pacman -Syyu --noconfirm --needed base-devel git |
| 168 | +``` |
| 169 | +This script sets up the fast mirrors for user in New Zealand. |
| 170 | +Alternatively, you can discover the nearest mirror list by running: |
| 171 | + |
| 172 | +```sh |
| 173 | +pacman -Sy --noconfirm reflector |
| 174 | +reflector --country New_Zealand --latest 5 --sort rate --save /etc/pacman.d/mirrorlist |
| 175 | +``` |
| 176 | + |
| 177 | +### Share Host SSH Keys |
| 178 | + |
| 179 | +By default, Lima mounts the your home directory under the `/Users` directory |
| 180 | +inside the VM. The second user provision script in the previous YAML |
| 181 | +setup the SSH keys sharing as follows: |
| 182 | + |
| 183 | +```sh |
| 184 | + if ! grep "User git" ~/.ssh/config; then |
| 185 | + HOST_USER=$(ls /Users) |
| 186 | + cat<<EOF >> ~/.ssh/config |
| 187 | + Host github.com |
| 188 | + User git |
| 189 | + Port 22 |
| 190 | + StrictHostKeyChecking no |
| 191 | + PasswordAuthentication no |
| 192 | + IdentityFile /Users/$HOST_USER/.ssh/id_ed25519 |
| 193 | + EOF |
| 194 | + fi |
| 195 | +``` |
| 196 | + |
| 197 | +This avoids duplicating the SSH keys in the ArchLinux VM. However, don't share |
| 198 | +your sensitive private SSH key like this when the applications running inside |
| 199 | +the VM can't be trusted. |
| 200 | + |
| 201 | +{{% callout warning %}} |
| 202 | +> **Security Alert**: Sharing your private SSH key poses a risk if the VM |
| 203 | +> runs untrusted applications. Consider generating a dedicated SSH key for VM |
| 204 | +> usage with limited access. |
| 205 | +{{% /callout %}} |
| 206 | + |
| 207 | +### Setup GUI Applications using X Window |
| 208 | + |
| 209 | +Even though LimaVM runs headlessly, you can still run GUI apps by pointing the |
| 210 | +DISPLAY to MacOS. The second user provision script sets up the DISPLAY |
| 211 | +environment variable as follows: |
| 212 | + |
| 213 | + ```sh |
| 214 | + if ! grep -e "^export DISPLAY=host.lima.internal:0" ~/.bashrc; then |
| 215 | + echo "export DISPLAY=host.lima.internal:0" >> ~/.bashrc |
| 216 | + fi |
| 217 | + ``` |
| 218 | + |
| 219 | +By this way, the DISPLAY environment variable is automatically exported when |
| 220 | +user logs in. The special hostname `host.lima.internal` is a Lima specific way |
| 221 | +to refer to the host. |
| 222 | + |
| 223 | +#### MacOS Setup |
| 224 | + |
| 225 | +MacOS doesn't come with compatible X Window server out-of-box. The XQuartz |
| 226 | +package is a good X Window server to use. |
| 227 | + |
| 228 | +1. **Install XQuartz on macOS** |
| 229 | + |
| 230 | + Download and install from [https://www.xquartz.org/](https://www.xquartz.org/). |
| 231 | + Or simply using Homebrew as: |
| 232 | + |
| 233 | + ```sh |
| 234 | + brew install xquartz |
| 235 | + ``` |
| 236 | + |
| 237 | +2. **Enable Connections** |
| 238 | + |
| 239 | + Open XQuartz preferences: |
| 240 | + |
| 241 | + - Go to *Security* |
| 242 | + - Check **Allow connections from network clients** |
| 243 | + - Quit XQuartz |
| 244 | + |
| 245 | +3. **Allow VM Access** |
| 246 | + |
| 247 | + Restart XQuartz and launch xterm and type: |
| 248 | + |
| 249 | + ```sh |
| 250 | + xhost + 127.0.0.1 |
| 251 | + ``` |
| 252 | + |
| 253 | + |
| 254 | +### Enable AUR and Install `yay` |
| 255 | + |
| 256 | +The [Arch User Repository (AUR)](https://aur.archlinux.org/) is a |
| 257 | +community-driven repository for Arch users, containing thousands of |
| 258 | +user-contributed packages. [`yay`](https://github.com/Jguer/yay) is a popular |
| 259 | +AUR helper that simplifies searching and installing AUR packages. |
| 260 | +The two components must be set up properly in order to install latest software |
| 261 | +conveniently. |
| 262 | + |
| 263 | +The previous example YAML's first user provision script sets up AUR and yay as |
| 264 | +follows: |
| 265 | + |
| 266 | +```sh |
| 267 | +cd /tmp && \ |
| 268 | + git clone https://aur.archlinux.org/yay.git && \ |
| 269 | + cd yay && \ |
| 270 | + makepkg --noconfirm -si && \ |
| 271 | + cd && \ |
| 272 | + rm -fr /tmp/yay |
| 273 | +``` |
| 274 | + |
| 275 | +## Launch and Validate |
| 276 | + |
| 277 | +### Launch the ArchLinux VM |
| 278 | + |
| 279 | +First, make sure Lima is installed, otherwise install it with Homebrew: |
| 280 | + |
| 281 | +```sh |
| 282 | +brew install lima |
| 283 | +
|
| 284 | +``` |
| 285 | +Then you launch the ArchLinux defined in previous YAML as follows: |
| 286 | + |
| 287 | +```sh |
| 288 | +limactl start archlinux.yaml |
| 289 | +
|
| 290 | +``` |
| 291 | + |
| 292 | +It takes a while to download the cloud image, create the vm and startup for the |
| 293 | +first time. |
| 294 | + |
| 295 | +### Validate the ArchLinux VM |
| 296 | + |
| 297 | +Once the ArchLinux is fully started, you can connect to it as follows: |
| 298 | + |
| 299 | +```sh |
| 300 | +limactl shell archlinux |
| 301 | +``` |
| 302 | + |
| 303 | +#### Test X Window Setup |
| 304 | + |
| 305 | +In the shell to the ArchLinux VM, install the `xeyes` package as follows: |
| 306 | + |
| 307 | +```sh |
| 308 | +sudo pacmac -Sy xorg-xeyes |
| 309 | +
|
| 310 | +``` |
| 311 | + |
| 312 | +Now you can test if X Window works properly by running `xeyes` inside the VM |
| 313 | +like: |
| 314 | + |
| 315 | +```sh |
| 316 | +xeyes & |
| 317 | +``` |
| 318 | +You should be able to see the eyes on MacOS screen. |
| 319 | + |
| 320 | + |
| 321 | +## Conclusion |
| 322 | + |
| 323 | +Running ArchLinux inside LimaVM provides a powerful and flexible development |
| 324 | +sandbox directly on macOS. With the ability to share SSH keys, run GUI |
| 325 | +applications via XQuartz, leverage fast mirrors, and access AUR packages using |
| 326 | +yay, it becomes a practical tool for developers looking to experiment with |
| 327 | +Linux environments efficiently and safely. |
| 328 | + |
| 329 | +For complete example source and launching script, visit the [Lima ArchLinux VM |
| 330 | +example](https://github.com/schnell18/vCluster/tree/master/lima/archlinux). For |
| 331 | +more information about Lima, visit the [LimaVM GitHub |
| 332 | +repo](https://github.com/lima-vm/lima). |
0 commit comments