runcmd and package order in Cloud-Init
Source: Dev.to
Question
How can a command specified in runcmd be executed before its related package is installed via the packages module in Cloud‑Init? Which module runs first?
Example
#cloud-config
package_update: true
package_upgrade: true
runcmd:
- systemctl enable --now qemu-guest-agent.service
packages:
- qemu-guest-agent
This pattern is common when provisioning VMs (e.g., with Terraform’s libvirt provider on QEMU/KVM). The runcmd entry tries to enable and start qemu-guest-agent.service even though the qemu-guest-agent package has not yet been installed. The guest agent is often needed early so that tools such as Ansible’s dynamic inventory can query host information.
Why it works
The confusion stems from the way Cloud‑Init’s module stages are documented:
- Config stage – where
runcmdis listed. - Final stage – where
packagesare installed and thescripts_usermodule runs.
Although runcmd appears in the Config stage, the commands under runcmd are not executed immediately. Cloud‑Init treats the runcmd list as a set of scripts that are scheduled to run later, specifically by the scripts_user module in the Final stage.
Consequently, the execution order is:
- Package installation (
packagesmodule) – Final stage. - User scripts (
scripts_usermodule) – Final stage, which runs the commands fromruncmd.
By the time scripts_user executes the systemctl enable --now qemu-guest-agent.service command, the qemu-guest-agent package has already been installed, the service file exists, and the command succeeds.