Where to start First steps track · 15 stages
Linux Labs

cloud-init — first-boot VM setup

4 min Ubuntu 24.04 · cloud-init

Automatic setup of cloud/virtual machines on first boot — user-data, debugging.

Cheat sheet

4 commands Printable version
  • cloud-init status --long status/errors
  • sudo cloud-init schema --system validate user-data
  • sudo less /var/log/cloud-init-output.log command output
  • sudo cloud-init clean --logs reset (to run again)
  • user-data: #cloud-config → users / packages / runcmd / write_files
  • disable it: /etc/cloud/cloud-init.disabled

Overview

cloud-init configures a machine on its first boot from an image: it creates users, drops in SSH keys, installs packages, writes files, sets up networking (netplan). Ubuntu cloud images support it out of the box.

bash
cloud-init status                 # execution status (done/running/error)
cloud-init status --long --wait   # wait for it to finish
cloud-id                          # which datasource (aws/azure/nocloud/…)

Stages: init-local → init → config → final. The config source (datasource): cloud metadata, NoCloud (ISO/seed), and so on.

Options

The configuration is passed as user-data. It starts with #cloud-config:

yaml
#cloud-config
hostname: web01
users:
  - name: deploy
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: [sudo, docker]
    ssh_authorized_keys:
      - ssh-ed25519 AAAA... me@laptop
package_update: true
packages: [nginx, htop]
write_files:
  - path: /etc/myapp/conf
    permissions: '0644'
    content: |
      key = value
runcmd:
  - systemctl enable --now nginx

runcmd runs commands at the final stage (once); bootcmd runs very early and on EVERY boot.

Recipes

1

Debugging

bash
cloud-init status --long          # done / error + details
sudo cloud-init schema --system   # check the user-data syntax
sudo cloud-init query userdata    # what the machine actually saw
# logs:
sudo less /var/log/cloud-init.log         # detailed module progress
sudo less /var/log/cloud-init-output.log  # runcmd/packages output (errors show up here)

# re-run when debugging an image:
sudo cloud-init clean --logs      # reset state and logs
sudo cloud-init clean --logs --reboot

Troubleshooting

5

user-data was not applied

  • The first line must be exactly #cloud-config (no leading spaces/BOM), and valid YAML (cloud-init schema --system).
  • It runs only on first boot (keyed by instance-id). To run again, use cloud-init clean or a new instance-id.

Packages didn't install / runcmd didn't run

/var/log/cloud-init-output.log has the command output and errors (no network for apt? a typo? a dependency?).

Can't SSH in after provisioning

The key never reached the right user, or the network (netplan) never came up. Check cloud-init logs plus the hypervisor console. Try cloud-init query userdata.

Hostname/network "revert" to default

cloud-init resets them on every boot unless you disable that: preserve_hostname: true, or network: {config: disabled} (see hostnamectl, netplan).

Disable cloud-init entirely

sudo touch /etc/cloud/cloud-init.disabled (or remove the package).

See also

  • netplan — Persistent network configuration on Ubuntu — YAML, static IP and DHCP, safe apply.
  • users-groups — Accounts, groups, membership; useradd/usermod, /etc/passwd and /etc/group.
  • ssh-keys — Key generation, authorized_keys, ssh-agent, permissions on .ssh files.
Loading…