cloud-init

Instance initialization system - user-data configuration, network setup, and Proxmox integration.

cloud-init Basics

Check cloud-init status
cloud-init status --long
status: done
time: Thu, 10 Apr 2026 08:15:32 +0000
detail:
DataSourceNoCloud [seed=/dev/sr0][dsmode=net]
Validate user-data before deploying
cloud-init schema --config-file user-data.yml
View rendered configuration
cloud-init query userdata
Analyze boot timing
cloud-init analyze blame
-- Boot Record 01 --
     3.42s (modules-config/config-runcmd)
     1.87s (modules-config/config-apt-configure)
     0.52s (init-network/config-growpart)
Re-run cloud-init (testing)
cloud-init clean --logs
cloud-init init
cloud-init modules --mode=config
cloud-init modules --mode=final

GOTCHA: cloud-init only runs on first boot by default. Use cloud-init clean to reset.

User-Data Configuration

Minimal user-data
#cloud-config
hostname: web-01
fqdn: web-01.inside.domusdigitalis.dev
manage_etc_hosts: true

users:
  - name: ansible
    groups: wheel
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh_authorized_keys:
      - ssh-ed25519 AAAA... ansible@controller

package_update: true
package_upgrade: true
packages:
  - vim
  - htop
  - qemu-guest-agent

runcmd:
  - systemctl enable --now qemu-guest-agent
Network configuration (v2 / Netplan)
#cloud-config
network:
  version: 2
  ethernets:
    eth0:
      addresses:
        - 10.50.1.101/24
      gateway4: 10.50.1.1
      nameservers:
        addresses:
          - 10.50.1.50
        search:
          - inside.domusdigitalis.dev
Write files
#cloud-config
write_files:
  - path: /etc/motd
    content: |
      *** Managed by Ansible ***
      Unauthorized access prohibited.
    permissions: '0644'

  - path: /etc/sysctl.d/99-hardening.conf
    content: |
      net.ipv4.ip_forward = 0
      net.ipv4.conf.all.send_redirects = 0
    permissions: '0644'
Disk setup and mounts
#cloud-config
disk_setup:
  /dev/vdb:
    table_type: gpt
    layout: true

fs_setup:
  - device: /dev/vdb1
    filesystem: ext4
    label: data

mounts:
  - [/dev/vdb1, /data, ext4, "defaults,noatime", "0", "2"]

Proxmox Integration

Terraform + cloud-init on Proxmox
resource "proxmox_vm_qemu" "node" {
  name        = "web-01"
  target_node = "pve"
  clone       = "rocky9-template"
  agent       = 1
  os_type     = "cloud-init"

  # cloud-init parameters
  ciuser     = "ansible"
  sshkeys    = file("~/.ssh/id_ed25519.pub")
  ipconfig0  = "ip=10.50.1.101/24,gw=10.50.1.1"
  nameserver = "10.50.1.50"
  searchdomain = "inside.domusdigitalis.dev"
}
Packer template prep (clean before converting)
# Run inside Packer provisioner before template conversion
cloud-init clean --logs --seed
truncate -s 0 /etc/machine-id
rm -f /var/lib/dbus/machine-id

PIPELINE: Packer builds template with cloud-init installed → Terraform clones template → cloud-init configures on first boot.

Debugging

Log locations
# Primary log
cat /var/log/cloud-init.log

# Output from runcmd and scripts
cat /var/log/cloud-init-output.log

# Instance data
cat /run/cloud-init/instance-data.json | jq '.v1.instance_id'
Query instance metadata
cloud-init query instance_id
cloud-init query ds.meta_data
cloud-init query userdata

DEBUG PATTERN: cloud-init analyze show reveals which module is slow or failing.

Quick Reference

Task Command

Validate user-data

cloud-init schema --config-file user-data.yml

Check status

cloud-init status --long

Re-run cloud-init

cloud-init clean && cloud-init init

Show rendered config

cloud-init query userdata

View boot log

cat /var/log/cloud-init-output.log

List modules run

cloud-init analyze show

Debug boot time

cloud-init analyze blame

Dump instance metadata

cloud-init query ds