cloud-init is a popular mechanism for initializing cloud server images. It is supported by most major Linux distributions and is available with most public cloud providers. I use it on a self-hosted Proxmox node with an Ubuntu Cloud image. I am also installing the following packages automatically with cloud-init:
qm disk import 9000 noble-server-cloudimg-amd64.img local-lvm
Attach the new disk to the VM as a scsi controller.
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0
Add the cloud init drive.
qm set 9000 --ide2 local-lvm:cloudinit
Make the cloud init drive bootable and restrict BIOS to boot from disk only.
qm set 9000 --boot c --bootdisk scsi0
Add serial console.
qm set 9000 --serial0 socket --vga serial0
Enable qemu guest agent.
qm set 9000 --agent enabled=1,freeze-fs-on-backup=1,fstrim_cloned_disks=1
Enable snippets storage in Proxmox GUI.
Create cloud init vendor config.
var/lib/vz/snippets/9000-civendor.yaml
#cloud-config# Updatespackage_update: truepackage_upgrade: true# Install packagespackages: - qemu-guest-agent - git - nfs-commonruncmd: # Start qemu-guest-agent - systemctl start qemu-guest-agent # One-command install, from https://tailscale.com/download/ - ['sh', '-c', 'curl -fsSL https://tailscale.com/install.sh | sh'] # Set sysctl settings for IP forwarding (useful when configuring an exit node) - ['sh', '-c', "echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf && echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf && sudo sysctl -p /etc/sysctl.d/99-tailscale.conf" ] # Generate an auth key from your Admin console # https://login.tailscale.com/admin/settings/keys # and replace the placeholder below - ['tailscale', 'up', '--authkey=tskey-REPLACE_ME'] - # (Optional) Include this line to make this node available over Tailscale SSH - ['tailscale', 'set', '--ssh']# Set timezonetimezone: "Europe/Brussels"
Add this vendor config to your VM.
qm set 9000 --cicustom vendor=local:9000-civendor.yaml