Tutorial: Create a custom image

When we talk about creating custom OS images for MAAS, it feels like something that’s about to get really complex. But with packer-maas, that’s often not the case.

Let’s see if we can’t create and deploy a custom Ubuntu image with packer, just to see how easy it can be.

First, install MAAS

If we’re going to create custom images for MAAS, then first, we’ll need MAAS! You can use this tutorial to accomplish that, and get a feel for MAAS while you’re at it.

Install packer

The next step is to install the tool packer, which will do the heavy lifting for us. Packer is easily installed from its Debian package:

sudo apt install packer

This should install with no additional prompts.

Install dependencies

We’re going to create a “custom” Ubuntu image for this build, so we’ll want to install a few dependencies. Enter the following commands. Don’t worry about any output between commands:

sudo apt install qemu-utils
sudo apt install qemu-system
sudo apt install ovmf
sudo apt install cloud-image-utils

Get the packer templates

Packer uses “templates”, which are very much like scripts that build your custom image. You can obtain the packer templates by cloning the packer-maas github repository, like this:

cd ~
mkdir -p tmp/git
cd tmp/git
git clone https://github.com/canonical/packer-maas.git

Make sure to pay attention to where the repository is cloned, in this case, tmp/git in your home directory. The packer template in this cloned repository creates a Ubuntu AMD64 image for use with MAAS.

Build an Ubuntu image

Now that we have that, let’s build a custom Ubuntu image that we can deploy with MAAS. Use these commands to do that:

cd ~/tmp/git/packer-maas/ubuntu
make custom-ubuntu-lvm.dd.gz

This make will run for a couple of minutes before attempting to boot the image. While waiting for the image to boot, you will see terminal messages similar to this one for upwards of three to five minutes:

2022/05/09 15:50:46 packer-builder-qemu plugin: [DEBUG] handshaking with SSH
2022/05/09 15:50:50 packer-builder-qemu plugin: [DEBUG] SSH handshake err: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password], no supported methods remain
2022/05/09 15:50:50 packer-builder-qemu plugin: [DEBUG] Detected authentication error. Increasing handshake attempts.

That’s expected. Eventually, you should see a successful SSH connection:

2022/05/09 15:50:57 packer-builder-qemu plugin: [INFO] Attempting SSH connection to
2022/05/09 15:50:57 packer-builder-qemu plugin: [DEBUG] reconnecting to TCP connection for SSH
2022/05/09 15:50:57 packer-builder-qemu plugin: [DEBUG] handshaking with SSH
2022/05/09 15:51:17 packer-builder-qemu plugin: [DEBUG] handshake complete!

After this, a few more commands will run. Eventually the terminal screen will clear and show just one line, as follows:


That means you’ve successfully built the image! Just to prove it to ourselves, let’s take a couple of additional steps.

Validate the build

You can check the validity of the operation with a simple ls command in ~/tmp/git/packer-maas/ubuntu (where you ran the make command), like this:

stormrider@neuromancer:~/mnt/Dropbox/src/git/packer-maas/ubuntu$ ls
custom-ubuntu-lvm.dd.gz  packages      seeds-lvm.iso     user-data-lvm
http                     packer_cache  ubuntu-flat.json
Makefile                 README.md     ubuntu-lvm.json
meta-data                scripts       user-data-flat

See the custom-ubuntu-lvm.dd.gz file? That’s our image, ready to try out.

Upload the image to MAAS

You can upload your newly-created image with the following command:

$ maas admin boot-resources create \
    name='custom/ubuntu-raw' \
    title='Ubuntu Custom RAW' \
    architecture='amd64/generic' \
    filetype='ddgz' \

Deploy the image in MAAS

What good is an image if we can’t deploy it? Pick one of the VMs you created in the last tutorial and deploy your new OS image to it. Then use a command like this one to see it running:

maas admin machines read | jq -r '(["HOSTNAME","SYSID","POWER","STATUS",
"OWNER", "OS", "DISTRO"] | (., map(length*"-"))),
(.[] | [.hostname, .system_id, .power_state, .status_name, .owner // "-",
.osystem, .distro_series]) | @tsv' | column -t

--------     -----   -----  ------    -----  --      ------
valued-moth  e86c7h  on     Deployed  admin  ubuntu  focal
open-gannet  nk7x8y  on     Deployed  admin  custom  ubuntu-raw

It’s the machine named open-gannet in the listing above, but your machine name and $SYSID will be unique to your instance.

That’s all there is to it!

In a few simple steps, you’ve used packer to create a custom Ubuntu image, upload it to a running MAAS, and deploy it. There are many different custom images that can be deployed with MAAS – check this guide to learn more.