Customising Ubuntu Metal as a Service (MAAS) to deploy Puppet

If you are deploying Openstack then you will need a server deployment tool, to build the servers from power on, in order to then configure each server for Openstack.

Ubuntu Metal as a Service (MAAS) can be used to manage physical (or virtual) machines and automatically deploy operating systems to servers, you just need to be able to PXE boot your machines and pick up the DHCP server from MAAS.

If you want to use MAAS to deploy servers, you almost certainly also want to manage those servers using a configuration management tool.

You could use Juju which is Ubuntu's own tool for orchastration and configuration management.  But what if you want to use your own custom tool or one of the commonly used tools like Puppet, Chef etc?

Well, you can use user-data to install any software as part of the deployment process, you just need to customise MAAS with some additional commands to add your own customisations.

As an example, we will use MAAS to automatically deploy a puppet agent to any server deployed with MAAS that automatically connects back to a puppet master server and obtain it's additional configuration.

We will be using the current stable version of MAAS, MAAS 1.8 - Available from the MAAS PPA here: ppa:maas-maintainers/stable .

MAAS installation instructions are online here:

MAAS Image Customisation

Firstly there are 2 installers that MAAS can use, the older and more standard Debian Installer, which is useful on debian based linux distributions, but doesn’t handle anything else and the newer curtin installer, written by Canonical to handle multiple operating system installation based on copying an image file on to the hard disk and rebooting it.  The image MAAS copies therefore has to be a suitable image and to allow customisation on boot, i.e. it needs to have cloud-init installed.  When cloud-init boots, it searches the network for a suitable data source, in this case it has been given a hint on boot to look for the MAAS data source at the region controller IP address.  Cloud-init then connects to the MAAS region controller and downloads a customised cloud-init script to customise the image with it’s hostname, IP address and any custom drivers.  It is at this point that you have the opportunity to customise the cloud-init user data provided to the instance to make additional customisations.

MAAS Preseed and User-data Structure

MAAS preseeds and curtin user-data are found in /etc/maas/preseeds/ directory on the MAAS Region controller.  In this directory you will seed the older debian installer files named preseed_master… we are not concerned with those, let’s use the curtin installer so the same techniques could be used to customise other OSes, such as CentOS or even Windows.

So the files we are concerned with are named, curtin_userdata…

These files are loaded when the curtin installer is used to first install the image, so any customisations we run here are being done by default inside the ephemeral image which only exists during the installation phase and is destroyed after reboot, so to make any customisations to the target environment we need to use the command:

curtin in-target CMD

where CMD is the command we want to run inside the target environment that the server will reboot into once the curtin install is finished.

Also, in order to operate in a correctly initialised environment we should run all commands in a newly created shell environment with the command:

sh -c CMD

So, we have:

curtin in-target sh -c CMD

We will also need to put this into a YAML format file, so this will also need additional formatting.

When curtin loads the curtin_userdata file it will pick the one that is most specific to the machine and OS it is starting based on the following priority:


So, for example, if we want to customise the ubuntu trusty install then we would create a file called: curtin_userdata_ubuntu_amd64_generic_trusty

So, let’s do that now:

cp curtin_userdata curtin_userdata_ubuntu_amd64_generic_trusty

Now we can edit the file and make customisations only suitable for Ubuntu Trusty version (14.04).

So, let’s say we want to install puppet to all our nodes as they are started and get them to check in to our puppet master server.

We could modify the userdata as follows, to make sure the latest version of puppet is installed and is started on reboot.

This relies on the fact that the puppet master will be at the hostname “puppet” in the domain that is managed by MAAS, this is easily done if you manually deploy a node with the hostname “puppet” from MAAS, otherwise you would have to add a CNAME in the bind DNS server template in MAAS to point to the real hostname.

e.g. in /etc/maas/templates/dns/zone.template add:


where HOSTNAME is the real hostname of the puppet master.

These lines would be added to the section late_commands in the customised curtin_userdata:

puppet_00_get: ["curtin", "in-target", "--", "sh", "-c", "wget -O /tmp/puppetlabs-release-trusty.deb && dpkg -i /tmp/puppetlabs-release-trusty.deb"]

puppet_01_install: ["curtin", "in-target", "--", "sh", "-c", "apt-get update && apt-get -y install puppet"]

puppet_02_onboot: ["curtin", "in-target", "--", "sh", "-c", "sed -i /etc/default/puppet -e 's/START=no/START=yes/'"]

That would then download the latest release of puppet direct from puppetlabs and install it, then modify the default config file to enable puppet to start on boot.

After the install is completed and the late_commands are run, the system will then reboot off the newly installed hard disk into the newly installed OS and run puppet for the first time, this will generate a client certificate and submit it to the puppet server.

On the puppet server you would then either have to accept the certificate manually on the puppet master server using the command:

puppet cert sign HOSTNAME

where HOSTNAME is the hostname of the client.

Alternatively, you can set the puppet master to automatically sign certificates for you, but you should understand the security consequences for setting this, i.e. only do this in a secure environment as anyone will be able to join the puppet master without intervention from an administrator.  You can do this by changing a setting in /etc/puppet/puppet.conf:


If you do set this then this will automatically add any ubuntu trusty server to puppet automatically and all you have to do is allocate a role in puppet to the server to configure it.

This you could do from a puppet dashboard such as Puppet Enterprise or Foreman, for example.