I self-host some services on virtual machines (VMs), and I’m currently using Debian 11.x as the host machine relying on the libvirt infrastructure to manage QEMU/KVM machines. While everything has worked fine for years (including on Debian 10.x), there has always been one issue causing a one-minute delay every time I install a new VM: the default images run a DHCP client that never succeeds in my environment. I never found out a way to disable DHCP in the image, and none of the documented ways through cloud-init that I have tried worked. A couple of days ago, after reading the AlmaLinux wiki I found a solution that works with Debian.
The following commands creates a Debian VM with static network configuration without the annoying one-minute DHCP delay. The three essential cloud-init keywords are the NoCloud meta-data parameters dsmode:local
, static network-interfaces
setting combined with the user-data bootcmd
keyword. I’m using a Raptor CS Talos II ppc64el machine, so replace the image link with a genericcloud amd64 image if you are using x86.
wget https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-generic-ppc64el.qcow2 cp debian-11-generic-ppc64el.qcow2 foo.qcow2 cat>meta-data dsmode: local network-interfaces: | iface enp0s1 inet static address 192.168.98.14/24 gateway 192.168.98.12 ^D cat>user-data #cloud-config fqdn: foo.mydomain manage_etc_hosts: true disable_root: false ssh_pwauth: false ssh_authorized_keys: - ssh-ed25519 AAAA... timezone: Europe/Stockholm bootcmd: - rm -f /run/network/interfaces.d/enp0s1 - ifup enp0s1 ^D virt-install --name foo --import --os-variant debian10 --disk foo.qcow2 --cloud-init meta-data=meta-data,user-data=user-data
Unfortunately virt-install from Debian 11 does not support the –cloud-init network-config parameter, so if you want to use a version 2 network configuration with cloud-init (to specify IPv6 addresses, for example) you need to replace the final virt-install command with the following.
cat>network_config_static.cfg version: 2 ethernets: enp0s1: dhcp4: false addresses: [ 192.168.98.14/24, fc00::14/7 ] gateway4: 192.168.98.12 gateway6: fc00::12 nameservers: addresses: [ 192.168.98.12, fc00::12 ] ^D cloud-localds -v -m local --network-config=network_config_static.cfg seed.iso user-data virt-install --name foo --import --os-variant debian10 --disk foo.qcow2 --disk seed.iso,readonly=on --noreboot virsh start foo virsh detach-disk foo vdb --config virsh console foo
There are still some warnings like the following, but it does not seem to cause any problem:
[FAILED] Failed to start Initial cloud-init job (pre-networking).
Finally, if you do not want the cloud-init tools installed in your VMs, I found the following set of additional user-data
commands helpful. Cloud-init will not be enabled on first boot and a cron job will be added that purges some unwanted packages.
runcmd: - touch /etc/cloud/cloud-init.disabled - apt-get update && apt-get dist-upgrade -uy && apt-get autoremove --yes --purge && printf '#!/bin/sh\n{ rm /etc/cloud/cloud-init.disabled /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg && apt-get purge --yes cloud-init cloud-guest-utils cloud-initramfs-growroot genisoimage isc-dhcp-client && apt-get autoremove --yes --purge && rm -f /etc/cron.hourly/cloud-cleanup && shutdown --reboot +1; } 2>&1 | logger -t cloud-cleanup\n' > /etc/cron.hourly/cloud-cleanup && chmod +x /etc/cron.hourly/cloud-cleanup && reboot &
The production script I’m using is a bit more complicated, but can be downloaded as vello-vm. Happy hacking!