Skip to content

Running Incus containers in Macpine

Overview

Incus is a next generation system container manager with support for a wide number of Linux distributions. It provides a simple way to build, test, and run multiple Linux environments across a single machine or multiple compute clusters.

Under the hood, incus uses LXC, through liblxc and its Go binding, to create and manage the containers. However, incus relies on a number of Linux kernel features, such as CGroups and kernel namespaces, which aren't natively available on MacOS.

Macpine makes it possible to run Incus/LXC containers on MacOS with support for both amd64 and arm64 processors, through its lightweight virtualisation layer. This workflow makes it easy to develop and test incus containers locally.

Prerequisites

  1. Install QEMU and macpine
brew install qemu macpine
  1. Install the incus client
brew install incus

Install Incus

Now that that the system is ready, we can create a lightweight Macpine instance, which will be configured to run Incus. In your terminal run:

alpine launch --name incus --ssh 223 --port 8443

This will create a new instance called incus and forward port 8443 (the default port that the incus client uses to communicate with the incus server) of the instance to host. Macpine will attempt to match the native CPU architecture of your host to the correct instance image. However, if you can explicitly specify the architecture by adding either --arch aarch64 or --arch x86_64 to the above command.

Now lets install the incus daemon.

alpine exec incus -- "hwclock -s; wget https://raw.githubusercontent.com/beringresearch/macpine/main/scripts/enable_incus.sh"

alpine exec incus -- "ash enable_incus.sh"

When the script finishes execution, the incus daemon will be available at guest startup.

Configure incus

Before you can create an instance, you need to configure incus.

Run the following command to accept all automatic defaults:

alpine exec incus "incus admin init --auto"

For the purposes of this tutorial, it is recommended to accept default settings.

NOTE: the above command is executed inside your incus instance and is sandboxed from your host.

Configure incus remote

Set up your incus remote to communicate with the incus client on your host.

alpine exec incus "incus config set core.https_address 0.0.0.0:8443"
alpine exec incus "incus config trust add mymac"

The command generates and prints a token that can be used to add the client certificate.

NOTE: Make a note of the token as it will be used to authenticate the incus client.

Add the remote to your Incus client:

Now that the remote server is configured, lets finish by configuring the incus client and adding our incus macpine instance as a remote.

incus remote add incus https://127.0.0.1

Enter the trust token for incus that you've noted from the steps before.

Finally, set this remote as the default:

incus remote switch incus

That's it - you can now run incus containers through Macpine at nearly-native speeds!

Launching your first incus container

Incus containers can now be launched and manipulated through the incus client. On your mac run:

incus launch images:debian/bullseye debian

Connecting to your first incus container

incus exec debian -- bash

Saving VM status

You can save the Macpine VM image with your incus configuration for later use:

alpine publish incus

This will create a tar ball that can be imported using alpine import.

Cleanup

incus stop debian
incus delete debian
alpine stop incus
alpine delete incus