Skip to content
  • cloud-init
  • hosting

Prepare Alpine

Install alpine to a VM, I used the bootable iso and ran through setup-alpine, set it up as lvmsys Don't configure a user besides root.

This is the iso I used, I'm not saying use this one, there's a 3.18 out as I'm writing this


  1. 8-6-2023: This current version seems to fully work for my use cases so far.
  2. If you're testing with just proxmox's built in cloud-init, like I did to create my terraform CNC test vm, you must set the network config in the cloud-init to something. dhcp is fine. Otherwise your vm will have no network access.

Install cloud-init

Cloud init needs some dependencies to work. These dependencies will be different based on Alpine Version. I am using Alpine 3.17.2

apk add gcc linux-headers py3-pip musl-dev python3-dev e2fsprogs e2fsprogs-extra cloud-init \
 libblockdev lsblk parted sfdisk sgdisk lvm2 device-mapper \
 doas eudev mount openssh-server-pam sudo

Ensure sshd is using PAM

(Source: /etc/ssh/sshd_config to ensure that it defines "UsePAM yes"

# sed -i '/^.*?UsePAM *=.*?$/d' /etc/ssh/sshd_config  # Erase any lines in the config that match the pattern, just to make sure. It was commented out in my install by default. I didn't run this. 
echo "UsePAM yes" >> /etc/ssh/sshd_config

Why all the extra things? Why gcc?

cloud-init also relies on py3-pyserial and py3-netifaces (In some cases), but doesn't include them as dependencies with apk The way I've found to install them is with pip

pip install pyserial netifaces

If this command fails, it's because I forgot all the dependencies required at this point. You may need to install another package or two. When I make a cloud init template again, I'll try to remember to update this document if there are more dependencies.

Great, it's installed, but not enabled.

Simply running rc-update add cloud-init boot will NOT work. Instead run:



Now you have an image that's ready. Be careful, from this point on you cannot reboot this VM, it's set up in template state. If you reboot it it will run the cloud-init first boot, and will break things.

Next steps

Now you can lock down your template VM before converting it to a template. Lock out root access with passwd -l root

If you had any public ssh keys you can remove them from /root/.ssh/authorized_keys if you want.

Finish up

Once your image is fully ready, go ahead and shut down your VM. Once it's fully shut off, right click it in the proxmox ui and convert it to a template.


I set up qemu-guest-agent (with apk add) in my template, and set the guest agent option in the options setting in proxmox to enabled. Very useful if you know you're going to run proxmox as the host, this way any clones created from the template will already be setup to communicate with proxmox. Since I'm currently using docker for everything, I also installed docker. I suggest installing everything you commonly use into the template, because linked clones can just reference the data from the base template for thin provisioning, and even though you'll have multiple copies in memory you don't need to have multiple copies on disk.

10gb-alpine:/etc/init.d# nano /etc/init.d/cloud-init
10gb-alpine:/etc/init.d# passwd -l root
passwd: password changed.
10gb-alpine:/etc/init.d# echo "" > /root/.ssh/authorized_keys
in /etc/init.d/cloud-init in depend() {...} add the line needs podman (or docker) to make sure cloud-init starts after podman. or docker.

Alpine Notes

rc-update -a -u - Run this to ensure the rc boot system updates it's dependency trees. Especially if you make cloud-init start after (podman or docker) (This took me far to long...)



datasource_list: [ NoCloud, ConfigDrive ]