cloud-init Debugging & Troubleshooting Prompt
Diagnose why a cloud instance came up wrong — user-data that never ran, SSH keys or hostname not applied, a module that failed silently, or first-boot vs re-run confusion — by reading cloud-init's logs, stages, and datasource correctly.
- Target user
- Senior Linux admins and SREs debugging instance provisioning on cloud and virtualized platforms
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT
The prompt
You are a senior Linux platform engineer who has debugged thousands of cloud-init provisioning failures across AWS, Azure, GCP, OpenStack, and bare-metal/NoCloud (cloud image + seed ISO) deployments. You understand cloud-init's boot stages, the datasource discovery process, module frequency (`once` vs `always`), the difference between user-data not being fetched and user-data running but failing, and why "re-running the same image" often does nothing because instance-id didn't change. I will provide: - The symptom: SSH key/password not set, hostname wrong, packages not installed, a `runcmd`/`write_files`/`bootcmd` block that didn't take effect, the instance hung at boot, or cloud-init "did nothing" - Platform / datasource (AWS EC2, Azure, GCP, OpenStack, NoCloud/seed-ISO, VMware) - `cloud-init --version` and distro - Relevant log excerpts if available (`/var/log/cloud-init.log`, `/var/log/cloud-init-output.log`) - The user-data / cloud-config being supplied (sanitized) - Whether this is a brand-new instance or a cloned/re-launched image Your job: 1. **Establish which of the four failure classes this is** — the whole diagnosis hinges on it: - **(a) Datasource not detected / user-data never fetched** — cloud-init ran but found no config. Check `cloud-init query --all` / `/run/cloud-init/instance-data.json` and the datasource line in the log. - **(b) User-data fetched but not valid** — YAML parse error, missing `#cloud-config` first line, or a `#!/bin/bash` script treated as the wrong type. Check for `Failed to parse` / schema warnings. - **(c) A module ran and failed** — e.g. `runcmd` command returned non-zero, package repo unreachable. The error is in `cloud-init-output.log`, not the main log. - **(d) It "did nothing" on a re-launch** — the module frequency is `per-instance` and the instance-id was reused, so cloud-init considered itself already done. 2. **Read the stages correctly**. cloud-init runs in ordered stages — `init-local` (datasource + networking), `init` (network up, most config fetch), `config` (config modules), `final` (`runcmd`, scripts, `final_message`). Tell me which stage the failure is in and why that matters (e.g. a `runcmd` failure is in `final`, long after networking). 3. **Use the right diagnostic tools**, not guesswork: - `cloud-init status --long --wait` — overall state and which stage it stopped in. - `cloud-init analyze blame` / `analyze show` — per-module timing, to catch a module hanging (common: waiting on a network/metadata endpoint). - `cloud-init schema --system` (or `--config-file`) — validate the user-data BEFORE blaming runtime. - `cloud-init query userdata` / `query --all` — confirm what config the instance actually received. 4. **Understand module frequency**: `write_files`, `users`, `ssh` etc. run `per-instance` (once per instance-id). Explain that re-running cloud-init or re-launching a clone with the same instance-id will skip them, and give the correct way to force a re-run (`cloud-init clean --logs` then reboot, or bump the instance-id) — and warn that `clean` wipes state and is for testing/golden-image prep, not live hosts. 5. **For NoCloud / seed-ISO and templated images**: check that the seed's `meta-data` provides a fresh `instance-id`, that the ISO label is `cidata`, and that the golden image was cleaned before templating (a leftover `/var/lib/cloud` makes every clone think it's already provisioned). 6. **Networking-vs-config ordering gotchas**: `bootcmd` runs every boot very early (before network); `runcmd` runs once, late. A command that needs DNS in `bootcmd` will fail. Point out mismatches. Give me: (1) the failure class (a/b/c/d) with the specific log line that proves it, (2) the root cause, (3) the exact fix and the corrected cloud-config if the config is at fault, and (4) how to safely re-test (clean vs new instance). --- Symptom: [what should have happened vs what did] Platform / datasource: [AWS | Azure | GCP | OpenStack | NoCloud | VMware] cloud-init version + distro: [...] New instance or cloned/re-launched image: [...] user-data / cloud-config (sanitized): ``` [PASTE] ``` Log excerpts (cloud-init.log / cloud-init-output.log): ``` [PASTE] ```
Run this prompt with AI
Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.
Why this prompt works
“cloud-init didn’t work” collapses four completely different failures into one sentence: the datasource was never found, the user-data was malformed, a module ran and errored, or the instance skipped provisioning because it reused an instance-id. Each has a different proof in a different log and a different fix, and guessing wastes reboots. This prompt makes the model classify the failure from evidence first, read the correct stage and log, and only then propose a fix — including the frequently-missed “clone kept the old state” case that no amount of config editing will solve.
How to use it
- Say whether the instance is brand-new or a clone/relaunch — that alone often identifies the
per-instanceskip case. - Paste both logs —
cloud-init.logfor datasource/module flow,cloud-init-output.logfor the actual stdout/stderr of your commands. - Include the raw user-data, header line and all, so YAML/type problems are visible.
- Run
cloud-init status --longandanalyze blamebefore deciding anything is hung.
Useful commands
# Terminal state and which stage it ended in
cloud-init status --long
cloud-init status --wait # block until cloud-init finishes (useful in scripts)
# Validate user-data BEFORE blaming the runtime
cloud-init schema --system
cloud-init schema --config-file user-data.yaml
# What config did this instance actually receive?
cloud-init query --all
cloud-init query userdata
cat /run/cloud-init/instance-data.json | less
# Per-module timing — find the module that hung or was slow
cloud-init analyze show
cloud-init analyze blame
# The two logs that matter (they contain different things)
sudo less /var/log/cloud-init.log # datasource + module orchestration
sudo less /var/log/cloud-init-output.log # stdout/stderr of runcmd/scripts/packages
# Force a clean re-run (TESTING / golden-image prep ONLY)
sudo cloud-init clean --logs --seed
sudo reboot
Sealing a golden image (so clones actually provision)
# Run on the template just before you snapshot it
sudo cloud-init clean --logs --seed
sudo rm -rf /var/lib/cloud/*
sudo truncate -s 0 /etc/machine-id # regenerate unique machine-id on next boot
sudo rm -f /etc/ssh/ssh_host_* # regenerate unique SSH host keys
Skipping this is the number-one reason cloned instances share a hostname/identity and never re-run first-boot config.
Common findings this catches
- Missing
#cloud-configfirst line making cloud-init ignore an otherwise-valid file. runcmdthat failed (bad repo, missing binary) — visible only incloud-init-output.log, invisible in the main log.- Cloned image skipping provisioning because
/var/lib/cloudand the instance-id were carried over from the template. - A module hanging on an unreachable metadata/network endpoint — surfaced by
analyze blametiming. bootcmdvsruncmdmisuse — network-dependent work placed in the pre-network stage.
When to escalate
- Datasource detection failures rooted in the platform (IMDS disabled, wrong metadata endpoint, broken seed device) — a platform/networking issue, not a cloud-config issue.
- Provisioning that must be idempotent across many reboots — cloud-init is first-boot oriented; ongoing config belongs in Ansible/Puppet/Chef or a systemd unit, not
runcmd. - Vendor-specific agents (waagent on Azure, GCE guest agent) interfering with cloud-init’s networking or hostname — coordinate with the platform image maintainer.
Related prompts
-
Shared Library Loader (ld.so) & LD_PRELOAD Debug Prompt
Debug 'error while loading shared libraries', wrong-version symbol errors, and unexpected library resolution by reasoning about the dynamic linker's search order, ldconfig cache, RPATH/RUNPATH, and LD_PRELOAD/LD_LIBRARY_PATH overrides.
-
ss Socket State & TCP Backlog Triage Prompt
Read ss output to explain a connection problem — stuck SYN-RECV/CLOSE-WAIT/TIME-WAIT piles, full accept/SYN backlogs, or exhausted ephemeral ports — and pinpoint whether the app or the kernel is to blame.
-
Hostname and machine-id Clone Fix Prompt
Detect and repair duplicate /etc/machine-id, D-Bus IDs, and hostname collisions on VMs cloned from a template that cause DHCP lease, journald, and SSH host-key conflicts.
-
sosreport Diagnostic Bundle Review Prompt
Systematically read a RHEL/Rocky sosreport bundle to find the root cause of a performance, boot, or service incident without manually grepping hundreds of collected files.
More Linux Admins prompts & error guides
Browse every Linux Admins prompt and troubleshooting guide in one place.
Reading prompts? Get all 500 in one free PDF
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.