Automating KVM VM Deployment with cloud-init for Password-Based SSH Access

Download an Ubuntu 22.04 cloud image for your architecture:

wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img -O base-image.qcow2

Create a cloud-init configuration file named bootstrap.yaml to initialize system settings:

#cloud-config
users:
  - name: operator
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    home: /home/operator
    plain_text_passwd: Secret123
    lock_passwd: false

ssh_pwauth: yes
chpasswd:
  expire: false

hostname: kvm-node-01
manage_etc_hosts: true

Package the configuration into a temporary ISO:

cloud-localds seed.iso bootstrap.yaml

Deploy the virtual machine using virt-install, attaching both the base image and configuration ISO:

virt-install \
  --connect qemu:///system \
  --name lab-instance \
  --memory 4096 \
  --vcpus 2 \
  --disk path=base-image.qcow2,format=qcow2,bus=virtio \
  --disk path=seed.iso,device=cdrom \
  --os-variant ubuntu22.04 \
  --network network=default,model=virtio \
  --graphics none \
  --console pty,target_type=serial \
  --import \
  --noautoconsole

Verify the instance is active:

virsh list --state-running

Access the serial console to monitor boot progress (use Ctrl+] to exit):

virsh console lab-instance

Once boot completes, authenticate using the configured credentials:

kvm-node-01 login: operator
Password: Secret123

Inspect network configuration to discover the assigned address:

ip -4 addr show ens3

Typical output:

2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.122.45/24 brd 192.168.122.255 scope global dynamic ens3
       valid_lft 3592sec preferred_lft 3592sec

Establish remote access via SSH:

ssh operator@192.168.122.45

Tags: KVM cloud-init virt-install Ubuntu virtualization

Posted on Sat, 16 May 2026 08:51:42 +0000 by synstealth