cloud-init validator
Paste the user-data you are about to give a new server and get findings that say what to change and why, each tied to the cloud-init documentation. The file stays in this browser; a private key in it is masked at once.
Paste the text, or choose a file from your computer. Up to 1024 KiB.
0 of 1024 KiB
What it does
It reads a user-data file the way cloud-init does, as YAML 1.1, checks its structure against the official cloud-config schema of cloud-init 26.2, the same one the cloud-init Generator is checked against, and adds security rules the schema cannot express. Every finding names its rule, its line and key, why it matters, how to fix it and the cloud-init documentation behind it.
The rules
- AQ-CI-001 Error The
#cloud-configheader. Make#cloud-configthe first line of the file, with no blank line or comment before it. Source - AQ-CI-002 Info Formats that are not checked. To check the configuration itself, paste the
#cloud-configpart on its own. Source - AQ-CI-003 Error YAML that cloud-init can read. Check this line: indentation with spaces only, a space after each key's colon, quotes around values that contain
:or start with a special character, and every key once. Source - AQ-CI-004 Error Values that match the official schema. Give the value the form the cloud-init module reference describes for this key, then check again. Source
- AQ-CI-005 Medium Unknown keys. Check the spelling against the cloud-init module reference, or remove the key. Source
- AQ-CI-006 Low Deprecated keys. Move to the key the documentation names: deprecated keys are removed in a later release. Source
- AQ-CI-007 High Password login over SSH. Log in with SSH keys: set
ssh_pwauth: falseand put the public key underssh_authorized_keys. Source - AQ-CI-008 High Passwords in plain text. Prefer SSH keys and a locked password (
lock_passwd: true). If a password is needed, put a hash frommkpasswd --method=SHA-512inhashed_passwd. Source - AQ-CI-009 High Private keys. Treat the key as exposed: create a new key pair, replace the old key wherever it is trusted, and put only the public key (.pub) in the file. Source
- AQ-CI-010 High Other secrets. Remove it and rotate it. Deliver secrets after the first boot, for example from your provider's secret store or in a file you copy over SSH. Source
- AQ-CI-011 High Root login. Log in as a normal user with sudo: keep
disable_root: trueand give the keys to that user. Source - AQ-CI-012 High
curl | bashin runcmd. Install from the distribution's packages or a signed apt repository, or download the file, check its SHA-256, then run it. Source - AQ-CI-013 High write_files permissions. Set
permissionsto0600(or0640for a group) andownerto the user who needs the file. Source
How it works
- The file is read on this page, up to 1 MiB. Nothing is run, no server is contacted, and no URL in the file is opened.
- The first line must be #cloud-config. MIME multipart, scripts that start with #!, #include and Jinja templates are other user-data formats: the validator says so and only looks for secrets in them.
- The schema check reports the problem itself, not the schema's nesting: a wrong type at its key and line, a key cloud-init does not know (often a typo it would silently ignore), and keys the schema marks as deprecated, with their replacement.
- The security rules read the values: ssh_pwauth and sshd settings, passwords in users and chpasswd that are not hashes, private keys and tokens anywhere in the text, root login, a download piped into a shell in runcmd or bootcmd, and write_files modes that let every user change a file or read a key.
- Values that look like secrets are masked before they are shown, and the same file always gives the same result.
Example
A user-data file with common problems, checked by the validator:
#cloud-config
users:
- name: admin
passwd: Winter2026!
sudo: ALL=(ALL) NOPASSWD:ALL
ssh-authorized-keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGtsW8dDDRo1PUAvjfnHmMGtSMfOMJ4CgrmrQgdYLZeT admin@laptop
ssh_pwauth: true
pakages:
- nginx
write_files:
- path: /etc/app/app.conf
content: |
listen = 8080
permissions: "0666"
runcmd:
- curl -fsSL https://get.example.com/install.sh | bash
Its findings:
Findings
6 findings: 0 error, 4 high, 1 medium, 1 low, 0 info.
High4
- HighAQ-CI-008Line 4
users[0].passwdusers[0].passwdmust be a password hash, and this is not one (Wi•••): the password is in plain text, and it will not work.Fix: Prefer SSH keys and a locked password (
lock_passwd: true). If a password is needed, put a hash frommkpasswd --method=SHA-512inhashed_passwd. - HighAQ-CI-007Line 8
ssh_pwauthssh_pwauth: trueturns on password login over SSH, which bots on the internet try all day.Fix: Log in with SSH keys: set
ssh_pwauth: falseand put the public key underssh_authorized_keys. - HighAQ-CI-013Line 15
write_files[0].permissions/etc/app/app.confis written with mode 0666: every user on the server can change it.Fix: Set
permissionsto0600(or0640for a group) andownerto the user who needs the file. - HighAQ-CI-012Line 17
runcmd[0]runcmd[0]downloads a script and pipes it into a shell: whatever the server answers runs as root, unchecked.Fix: Install from the distribution's packages or a signed apt repository, or download the file, check its SHA-256, then run it.
Medium1
- MediumAQ-CI-005Line 9
pakagespakagesis not a key cloud-init knows here (pakages). cloud-init ignores it, so what it sets does not happen; it is often a typo.Fix: Check the spelling against the cloud-init module reference, or remove the key.
Low1
- LowAQ-CI-006Line 6
users[0].ssh-authorized-keysusers[0].ssh-authorized-keysis deprecated since cloud-init 18.3; usessh_authorized_keysinstead.Fix: Move to the key the documentation names: deprecated keys are removed in a later release.
Limits
- A static check: the file is not booted. A file that passes can still fail on a server, for example when a package or a URL does not exist, or the image's cloud-init is older than the schema.
- MIME multipart files, #include, boothooks and Jinja templates are not read, only scanned for secrets. Check the #cloud-config part on its own.
- Shell scripts in runcmd, bootcmd and write_files are not analyzed beyond the rules above.
- Provider-specific keys outside the official schema are reported as unknown.
Methodology: how the numbers are worked out
Sources
Related
Next step
A free public tool by ANAROQ, a company building compute infrastructure. What ANAROQ is building