Many sysadmins encounter situations where cloud-init unexpectedly re-executes during system reboots - even on fully provisioned systems. This behavior stems from cloud-init's default design to process user-data whenever it detects configuration changes. While this makes sense for dynamic cloud environments, it causes headaches in scenarios where:
- Manual configurations get overwritten (e.g., SSH host keys regeneration)
- Network settings revert to initial values
- Duplicate user accounts get created
Cloud-init determines whether to run through several mechanisms:
# Check current execution status
sudo cat /var/lib/cloud/instance/sem/config_scripts_user
The main trigger files reside in /var/lib/cloud/instance/sem/
where completion markers get created after each module runs.
Method 1: The Official Disable Flag
Create a disable file in the cloud-init configuration directory:
sudo touch /etc/cloud/cloud-init.disabled
sudo cloud-init clean --logs
Method 2: Cloud-Config Directive
Add this to /etc/cloud/cloud.cfg
:
# Disable cloud-init after first boot
cloud_init_modules:
- [scripts-user, once]
- [set-hostname, once]
- [update-hostname, once]
disable_root: true
preserve_hostname: true
Method 3: Systemd Unit Modification
For systems using systemd, mask the service:
sudo systemctl mask cloud-init.service \
cloud-init-local.service \
cloud-config.service \
cloud-final.service
For automated deployments, include this in your user-data:
#cloud-config
runcmd:
- [touch, /etc/cloud/cloud-init.disabled]
- [cloud-init, clean, --logs]
- [systemctl, mask, cloud-init.service]
power_state:
mode: poweroff
timeout: 30
message: Completed first boot configuration
After implementing any solution, verify with:
cloud-init analyze show
cloud-init status --long
systemctl list-unit-files | grep cloud-init
For cloned VMs or golden images, consider these additional measures:
# Clean cloud-init artifacts before templating
sudo cloud-init clean
sudo rm -rf /var/lib/cloud/instance
sudo rm -f /var/lib/cloud/instances/*
Cloud-init's default behavior of reprocessing user-data on configuration changes or reboots can cause operational issues in production environments. The most common pain points include:
- SSH host key regeneration breaking existing connections
- Network configuration reverting to template defaults
- Custom package installations running multiple times
Cloud-init executes through systemd services with these critical components:
cloud-init-local.service
cloud-init.service
cloud-config.service
cloud-final.service
Each stage evaluates the /var/lib/cloud/instance
directory's marker files to determine execution status.
Method 1: The Canonical Disable Flag
The most reliable approach creates a disable file:
sudo touch /etc/cloud/cloud-init.disabled
Method 2: Systemd Service Masking
For systemd-based distributions:
sudo systemctl mask cloud-init.service cloud-init-local.service \
cloud-config.service cloud-final.service
For template images or automated deployments, add this to your cloud-config:
#cloud-config
runcmd:
- [ sh, -c, "echo 'datasource_list: [ None ]' > /etc/cloud/cloud.cfg.d/90_disable_cloud_init.cfg" ]
- [ sh, -c, "touch /etc/cloud/cloud-init.disabled" ]
- [ systemctl, mask, cloud-init.service ]
- [ rm, -rf, /var/lib/cloud/instance ]
After implementation, verify with:
cloud-init status --wait
cloud-init analyze show
Check for persistent artifacts:
ls -la /var/lib/cloud/instance
journalctl -u cloud-init
When working with cloned VMs or golden images:
sudo cloud-init clean --log
sudo rm -rf /var/lib/cloud/instances/*
sudo truncate -s 0 /etc/machine-id