Cloud-init is a popular way to automate deployments of Linux instances in a cloud or non-cloud environment. To save having to repeat tasks, we can configure Cloud-init modules or Cloud-init scripts to set up networking and configure hostnames or even IP addresses. Snippets are used with the information required and Cloud-init scripts make the required changes. In this guide, we’re going to go through some Cloud-init modules that are appended to the Cloud-init configuration file located at /etc/cloud/cloud.cfg in Cloud Operating System images. You can run custom Cloud-init scrips on any NVMe VPS Server or High Availability VPS Server.
We have already covered how to create Cloud Operating Systems in the link above. Although aimed at Proxmox environments, it can be used to create Cloud images for any platform that utilizes Cloud-init. The guide above shows you how to edit the /etc/cloud/cloud.cfg file before creating an image. So first, open up the cloud.cfg file on any Cloud image. We are using the stock Ubuntu 22 LTS image.
cd /root
# Download a cloud image
wget https://cloud-images.ubuntu.com/jammy/20220622/jammy-server-cloudimg-amd64.img
# Set editor to use nano
export EDITOR=nano
# Use virt-edit to edit the image
virt-edit -a jammy-server-cloudimg-amd64.img /etc/cloud/cloud.cfg
So now in the console, you should be looking at the default cloud-init configuration file. Your file will likely look a bit different because we have already edited this to create an Ubuntu 22 Operating System for use on the NVMe VPS network.
Cloud-init Modules/Scripts
At the end of this file, we add further modules to expand what Cloud-init will do during boot. Let’s look at some modules.
bootcmd
bootcmd can be used to perform tasks that can’t be run later in the build process. This example set’s up our hostname in the /etc/hosts file. You shouldn’t use bootcmd to perform tasks like updates. That is done later in the build process.
- Runs: Always
- Support By: All Distributions
bootcmd:
- echo 168.115.114.0 uk.f2h.cloud > /etc/hosts
Timezone
The timezone Cloud-init module can be used to set a specific timezone in the instance.
- Runs: Always
- Support By: All Distributions
timezone: Europe/London
Write Files
The write files module can be used to append text to files or write new files on startup. This is useful if you want to add cron jobs, place a script in a specific directory or create an Apache Virtual Host for example.
- Runs: One Per instance
- Support By: All Distributions
# Add cron job to crontab
write_files:
- content: |
0/5 * * * * root sh /path/to/script.sh
path: /etc/crontab
append: true
# Create Apache virtual host
write_files:
- path: /etc/apache2/sites-available/f2h.conf
content: |
server {
server_name f2h.com www.f2h.com;
listen 80;
root /home/local;
location / {
try_files $uri $uri/ $uri.html =404;
}
}
owner: 'nginx:nginx'
permissions: '0640'
defer: true
Keyboard
The Keyboard module is used to set a different keyboard. So that’s very useful if you have users who use a different layout other than the default QWERTY. You use codes to set the layout.
- Runs: One per instance
- Support By: All Distributions
keyboard:
layout: uk
Power State Change
We can use the Power State Cloud-init module to perform tasks related to boots and reboots. The module directs the instance to reboot after X seconds. But there isn’t really any need for this because you can end up in an endless reboot loop. So if you need to reboot to apply updates. You can use the package_reboot_if_required statement.
- Runs: Always
- Support By: All Distributions
# Only reboot if package updates demand it
package_reboot_if_required: True
# Reboot after 30 seconds
power_state:
delay: 30
mode: reboot
message: Rebooting
condition: true
# Power off straight away and display message "Powering off"
power_state:
delay: now
mode: poweroff
message: Powering off
timeout: 2
condition: true
ResizeFS Cloud-init Script
ResizeFS will expand a root partition to use all of the available space. So imagine your instance has 100GB of space. You add a further 100GB. You have a total of 200GB but at the moment, only 100GB is available to use. ResizeFS will automatically expand your 100GB root partition to 200GB. ResizeFS blocks the boot process until it has completed its task.
- Runs: Always
- Support By: All Distributions
# Disable automatic resize.
resize_rootfs: false
# Enable automatic HDD resize in the background
resize_rootfs: noblock
Final Message
The final message cloud-init script will print a message to the console once Cloud-init has completed all tasks.
- Runs: Always
- Support By: All Distributions
# Basic Message
final_message: This F2H instance is ready for production.
# Advanced with switches
final_message: |
This F2H instance is ready for production.
version: $version
timestamp: $timestamp
datasource: $datasource
uptime: $uptime
So these are just a few of the less common Cloudinit modules you can use to automate tasks at startup. Sometimes it may be better to use a SystemD service and bash script to run at startup other than cloud-init.
A full list of Cloud-init modules and Cloud-init script can be found using the Cloud-init module reference guide.