Free — no signup required

Cloud-Config Syntax Essentials

2 min read

Doing It Declaratively

The cloud-config format gives you a structured vocabulary for the most common server setup tasks. Instead of writing imperative Bash to create a user, set permissions, and inject a key, you declare the desired state and cloud-init handles the implementation.

Here is what a realistic cloud-config combines in practice: flags to update and upgrade the package index, a packages list, a users entry creating a service account with a passwordless-sudo rule and an SSH public key, a write_files section that drops an Nginx site config and a placeholder index page onto disk, and a closing runcmd list that validates the Nginx config, enables and starts the service, and logs completion. Every one of those is a declarative key — cloud-init's modules take care of actually creating the user, writing each file with the right owner and permissions, or invoking the equivalent shell commands.

Key modules and their semantics:

Module Key What It Does
Package management packages, package_update, package_upgrade Installs packages via the native package manager (apt, yum, dnf)
User management users Creates users, sets shells, injects SSH keys, configures sudo
File writing write_files Creates files with specified content, owner, and permissions before runcmd
Command execution runcmd Runs a list of shell commands at the very end of the Final stage
Hostname hostname Sets the system hostname
NTP ntp Configures NTP servers
Disk setup disk_setup, fs_setup, mounts Partitions, formats, and mounts additional block devices

Order of execution within cloud-config:

write_files runs before runcmd. This means you can write a config file and then reference it in a command — a common pattern for deploying application configs before starting services.

The runcmd vs. bootcmd distinction:

runcmd runs once, in the Final stage, on first boot only. bootcmd runs on every boot, very early (before network). Use bootcmd sparingly — it's for things like setting kernel parameters that must be applied before any service starts.

Interview Tip

A common interview question: "How do you make cloud-init run your script on every reboot, not just the first boot?" The answer is: you generally don't — cloud-init is a first-boot tool by design. For recurring tasks, write a systemd unit or cron job. If you genuinely need cloud-init to re-run (e.g., in a testing environment), you can delete /var/lib/cloud/instance and reboot, which makes cloud-init treat the next boot as a first boot. In production, this is almost never the right answer.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free