Deploying Custom Images

Hi guys,

I’m trying to create a custom image and deploy it to a node.

However I’m having issues with downloading/extracting the images on the new node.
I’m creating a boot-resource with the following command:

maas $PROFILE boot-resources create name=custom/my_image architecture=amd64/generic content@=my_image_path

From maas $PROFILE boot-resources create --help I can read it accepts the image as a .tgz file.
So I compress the image before creating a boot-resource out of it:

sudo tar -cvzf my_image.tgz /path/to/squashFS/image/

When I then deploy to the node, my_image.tgz is downloaded and I get the following error:

curtin: Installation failed with exception: Unexpected error while running command.
cloud-init[1296]: Command: ['curtin', 'curthooks']
cloud-init[1296]: Exit code: 3
cloud-init[1296]: Reason: -
cloud-init[1296]: Stdout: 'ID'

Can anyone tell me what that error means and possible how to address it?


What, where, and how are you creating the custom image? It’s not clear to me if the maas folks are really keen on helping on how to create proper custom images. We figured it out, though, and wrote a script that will create custom kubernetes images we use within our environment.

Based on your output, it looks like your creation of the image at least semi-works (boots), but your curtin isn’t right. The use of content@=... suggests you’re trying to use cloud-init/userdata. Your output suggests your userdata is wrong. Try booting without the content@=... and see if you can at least get a booted image. If you do, then your image is fine and your cloud-init is what needs help.

Thanks for the answer @snafuxnj

I’m actually just using a clean squashFS image. I haven’t modified anything in it. I pull it down with:

sstream-mirror --max=1 --progress --keyring=$KEYRING_FILE $IMAGE_SRC $IMAGE_DIR 'arch=amd64' 'release~(bionic)' 
sstream-mirror --max=1 --progress --keyring=$KEYRING_FILE $IMAGE_SRC $IMAGE_DIR 'os~(grub*|pxelinux)' 

Then I point the boot-resources create command at the path of the squashFS image.

I tried copying over the ga-18.04 image, which MaaS provides as well (which I have no problem deploying with), and the same error occurs. So I assume it is something with the curtin that isn’t right, just as you said.

If I create a boot-resource without content@= what will the node boot to?

Can you please post a full log ?

Her you go:

curtin: Installation started. (18.2-10-g7afd77fa-0ubuntu1~18.04.1)
Creating new GPT entries.
The operation has completed successfully.
mkfs.fat: warning - lowercase labels might not work properly with DOS or Windows
mkfs.fat 4.1 (2017-01-24)
–2019-05-21 17:57:59-- tgz
Connecting to… connected.
HTTP request sent, awaiting response… 200 OK
Length: 1946673152 (1.8G) [text/html]
Saving to: ‘STDOUT’

 0K .tar: This does not look like a tar archive
tar: Skipping to next header
....... ........ ........ ........ ........ ........  0% 69.6M 27s
3072K ........ ........ ........ ........ ........ ........  0% 99.1M 23s
6144K ........ ........ ........ ........ ........ ........  0% 99.1M 21s
9216K ........ ........ ........ ........ ........ ........  0%  100M 21s

A long download sequence I’m going to spare you

1889280K ........ ........ ........ ........ ........ ........ 99% 87.4M 0s
1892352K ........ ........ ........ ........ ........ ........ 99% 90.7M 0s
1895424K ........ ........ ........ ........ ........ ........ 99% 89.3M 0s
1898496K ........ ........ ........ ........ .......          100% 88.0M=20s
2019-05-21 17:58:19 (90.6 MB/s) - written to stdout [1946673152/1946673152]
tar: Exiting with failure status due to previous errors
Unexpected error while running command.
Command: ['sh', '-cf', 'wget "$1" --progress=dot:mega -O - |smtar -C "$2" --xattrs --xattrs-include=* -Sxpf - --numeric-owner', '--', '', '/tmp/tmpjv_7kekm/target']
Exit code: 2
Reason: -
Stdout: ''
Stderr: ''

MAAS only supports custom images which are DD(full disk image) or tar(archive containing all system files). In either case the custom image must have all all files required to boot in the image. For Ubuntu images coming from we ship the base OS image as a SquashFS file with the kernel and initrd as separate resources. This allows MAAS to make the Ubuntu images available for PXE booting in addtion to deployment. We do not currently support SquashFS images for custom image deployment nor do we support PXE booting images that do not come from

For Ubuntu customization I suggest using cloud-init or preseeds.

Could you share your setup/script? I was trying to build a custom Debian image without success. Even something with a basic pre-seed would be fine.

If you look around, there is a lot of questions regarding custom images but very little documentation. Which I understand from a business/Canonical perspective but it’s a bit frustrating when you have Foreman/Katello that can do Debian.

Especially considering how close Debian and Ubuntu are.

Yup! I feel your frustration! It was kind of a pain figuring out how to do it. So, if you take a look at then that should hopefully get you started. Feel free to ask questions. BTW, I’m being purposely vague, but perhaps that is not necessary. So if you need more assistance, let me know. You can also get some interesting information from

The script I linked there is not meant to be downloaded and run by itself. You’ll need to look at the image-creation directory there as the structure is important! There are support scripts in the respective distro directories that are important with respect to the build system my teammate and I built there. The script was written by me. It has all the essential pieces you need to know how to get a proper image from Canonical and then open it up, mount it, alter it, and tar it back up once completed. Finally, if you need help learning how to import the new image to maas, I can assist with that as well.

1 Like

That’s just awesome. I’ll take a crack at it tomorrow and see if I can wrangle a base Debian image. I really appreciate the time you took for the repo readme, it looks super clear.

I’ll reach back if I can’t figure it out but either way, thank you! If you are ever in Quebec, I’ll gladly get you a beer!

1 Like


I was able to play around with this a bit more and I’ve been able to successfully deploy a pretty basic base image made from the .raw images for Debian on Openstack. That said, i’m facing a lot of issues with cloud-init. It appears that the MAAS datasource is never properly configured during Curtin which means that cloud-init fails during the first “real” boot as it doesn’t have the proper parameters to reach MAAS.

I’ll poke at this a bit more but I feel like MAAS is a bit clunky with Debian. :frowning:

Which version of MaaS are you using?

I am currently running 2.5.3

OK good. So whatever you might get working with the stuff I provided should work with 2.5.3 as that is the version we are also using.

Hi @snafuxnj, I finally got around to look at the image creation again. However it seems like the repo you are linking to have been moved/deleted. Could you assist with a new url?

Hey @chrkong! yup. They moved to

I get a 404 on the link :frowning:
Is it not a public repo?

ah crap! Yeah, we pulled it back in as a private repo a few weeks ago. I’m really sorry. I can’t provide it to you either since we made it private. I can give pointers, though. I’ll ask if I can make that available to you.

Thanks @snafuxnj!
I’m current process so far is:
I downloaded a fresh image from, specificly the bionic-server-cloudimg-amd64-root.tar.xz image. I made it a custom MAAS boot resource with the first command in my original post. Delpoyed it and everything was fine :ok_hand:

Now I wanted to customize that image before deploying, which is the whole point, right. So I unpack, mount, chroot into it, do my thing, umount, package it up again, make it a new boot resource and deploy it. And now it doesn’t work :frowning: . Do you know how my tar command should look like to package an image back up again? Or is there any specify things I need to be aware of when I chroot into my image to customize it, that I might have missed?

yup! First, apologies for slow response. I’ve been on vacation.

Here’s the info you need:

When you chroot into the image, you want to make sure, probably, that you mount/bind your proc, sys, and dev filesystems from your host machine to your chrooted environment. Do NOT forget to unmount those when you’re done (after you exit your chroot).

Then tar should be:

tar cpzf $TARGET -C "$CHROOTED_ROOT" .
note that the -C "$CHROOTED_ROOT" is optional depending on from where you tar the archive.

If you need more pointers, let me know. I’ll be more specific.

No worries.
I figured out that my mistake was in my tar command. I archived the folder and the unpacked content instead of just the content.

Thanks for all the help!