Proxmox, How To Create An Alpine Cloud-Init Image
In the video below, we show how to create an Alpine Linux Cloud-Init image for Proxmox VE
Now as much as I prefer Debian over other Linux distros, after a while the packages in the repository become out of date
At the time of recording for instance, Debian 12 offers version 4.3.1 of Podman which is 2 years out of date
For other software I’ve used pip and homebrew for instance to get the latest version, but the developers of Podman recommend to use the official repository for installation
Now, Debian 13 is targeting version 5.2.x but it’s still in a state of work-in-progress
And over time that version while become out of date as well
Enter Alpine Linux, which stays up to date
Now although Alpine Linux has cloud-init images, even as of 2024, all but the AWS ones are either in Beta or Alpha
And try as I might, I couldn’t get one to work in Proxmox VE
So how do you create your own cloud-init version of Alpine Linux?
Well if that’s something you’re interested in finding out then stick around and watch this video as that’s what we’ll be going over
Useful links:
https://docs.alpinelinux.org/user-handbook/0.1a/Installing/setup_alpine.html
https://wiki.alpinelinux.org/wiki/Upgrading_Alpine
https://wiki.alpinelinux.org/wiki/Local_APK_cache
https://git.alpinelinux.org/aports/tree/community/cloud-init/README.Alpine
https://docs.alpinelinux.org/user-handbook/0.1a/Working/post-install.html
https://wiki.archlinux.org/title/Doas
https://wiki.alpinelinux.org/wiki/OpenRC
https://cloudinit.readthedocs.io/en/latest/reference/base_config_reference.html
https://cloudinit.readthedocs.io/en/latest/reference/datasources.html#datasources
https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_and_managing_cloud-init_for_rhel_9/introduction-to-cloud-init_cloud-content#cloud-init-acts-upon-user-data-and-metadata_introduction-to-cloud-init
https://www.ibm.com/docs/en/powervc-cloud/2.2.1?topic=aix-custom-powervc-cloud-init-modules
https://www.ibm.com/docs/en/rsct/3.3?topic=subsystem-rmc-usage-hmc
Download ISO Image:
Now because we won’t be using a pre-built cloud-init image, the first thing to do is to download a suitable ISO file which you’ll find here
https://alpinelinux.org/downloads/
One of the slimmed down ones intended for virtual systems makes more sense to me, and you’ll find files for various processor architectures under the VIRTUAL section
Typically you’ll want to choose the x86_64 version which is for Intel and AMD 64 bit processors
From a security perspective it makes sense to check the file hasn’t been tampered with so click the SHA256 button next to the file to download the checksum
Once the file’s downloaded you’ll want to upload it to somewhere where at least one of your servers can access
In this demo I’ll upload it to the local storage of a server
To check the file integrity you’ll want to set the Hash algorithm to SHA256 in this case and copy and paste in the checksum
Assuming everything checks out, the file will be uploaded and ready for use
Create VM:
The next thing to do is to create a VM using the ISO image we’ve downloaded
Pick the server in the GUI you want to create a VM on and click Create VM in the top right corner
If this will become a template then you might want to set the VM ID to a higher number so that it stands out and is easier to find
I tend to use 9000 upwards when creating templates but it’s up to you
TIP: Proxmox VE 8.3 introduced a tag view so you could use that as another option
Enter a name, for example, AlpineTemplate then change any other settings you think may be relevant
Now click Next
We want to install the OS from the ISO we just downloaded so from the ISO image drop down menu select that file
Leave the Guest OS settings as is and click Next
You’ll probably want to leave the System settings as is, although I prefer to enable the Qemu Agent option
Unless the OS of a VM doesn’t support the qemu agent, enabling this now means that once the client software is installed, PVE will be able to better understand resource usage in the VM, but it will also be able to shut it down or restart it gracefully
Since Alpine will support the agent, we’ll enable this
Now click Next
The VM needs a hard drive for us to install the OS in and by default this one will given 32GB
Alpine Linux uses very little disk space, so as this won’t become used as a VM I’ll change this to 1GB to save storage space
Any clones I make will have their disk capacity increased as needed
Now click Next
Typically for VMs, I leave Sockets set to 1 and only change the Cores option to decide how many vCPUs a VM should have
Because this is a template, I’ll leave this also set to 1, to show that’s enough to install and run the OS
But you can always set this to a more common amount for future VMs
The type of CPU really depends on the system(s) you’re running
Ideally you should change this to host to get the best performance, but that can be a problem in a cluster where the servers don’t have identical CPUs
Because when the CPUs don’t match, you can’t perform a live migration of a VM from one server to another if the processor in the VM is using an instruction set the CPU on the target server doesn’t have
In addition, you shouldn’t mix different vendor CPUs in a cluster
So if the servers aren’t identical you should instead opt for whichever emulated processor will work on all servers
There are various other settings which are a bit more advanced, so typically you would just click Next
Because this is a template you may want to change the memory settings to a common value you’d expect for clones
I would suggest disabling the Ballooning Device option though as it can lead to performance problems
It only makes sense in labs where RAM is limited because what the hypervisor will do is fool the VM into thinking it has RAM when actually it uses hard drive storage
For instance, lets say a VM has 4GB of RAM but only uses 1GB, well PVE might allocate it 2GB of RAM and 2GB of disk storage
The problem is when the VM suddenly needs 3GB of RAM, PVE has to do a bit of juggling and in the meantime the VM is reading or writing to disk instead of RAM and so the performance suffers
Now click Next
The network settings really depend on your circumstances, but typically you’d only consider changing the Bridge and VLAN Tag
Ones those have been decided, click Next
You can check the summary at the end and if these look fine, click Finish
Install OS:
Power up the VM and connect to it via the console
NOTE: We won’t have access to SPICE and VNC doesn’t support copying and pasting
For the login username enter root, hit return and you’ll be taken to the command prompt as the Live CD has no password
To install Alpine onto the hard drive of the VM, run this command
setup-alpine
This will then take you through a wizard
TIP: The documentation mentions a quick mode, and even hints at using an answer file but that’s beyond the scope of this video
Some of these settings can be left with their default option, some depend on your circumstances, but there are some I’ll draw attention to
When asked for the Hostname, enter the Fully Qualified Domain name, for example
alpinetemplate.homelab.lan
In this example, the computer will be called alpinetemplate and the domain name for my lab is homelab.lan
When selecting an APK Mirror it would be good to enter f and let the computer find the closest mirror to you rather than defaulting to say the first one. This should make it quicker to download future updates
It does take a while mind as there are quite a few options to test against
TIP: You can always repeat or do this later if you prefer by running this command
setup-apkrepos
You’ll be asked after that if you want to create a new user account
TIP: Pay attention! If you want to create a user account, enter the name of the user as the answer. The start of the line implies this is a yes/no question but if you enter yes, guess what, you’ll end up with a user called yes. Doh!
Bear in mind, this user will become a member of the wheel group, as will an account created using cloud-init
And this could become a problem, as we’ll cover later, if you prefer to use sudo
Personally I prefer not to leave accounts on a template VM, other than root obviously for Linux, so I’ll not create a user account
The reason being, every new VM cloned from this one will have this user account installed and it could become compromised somewhere down the line
Even if it didn’t, at later date you may decide to use a different account but your template will be stuck with this one
The benefit of letting cloud-init create a user account is that the account isn’t created until the VM boots up for the first time and runs the cloud-init process
That feels like a better choice to me so we’ll use that method later
In any case, if you do opt to create a user account then doas will be installed
If you’re not familiar with doas, it’s similar to sudo, to gain elevated privilege
You’ll be asked if you want to allow root ssh login and although we don’t have another account yet, I suggest leaving this with the default setting of prohibit-password
You could in theory enter an SSH key for root, but I don’t see that being practical through this console session as we can’t paste into it
When setting up the hard drive, there are various choices
Because this is a basic installation of just the operating system, I’ll opt to set the drive up as a sys drive, although there are other options including encryption
You’ll want to enter y at the end when asked to erase the disk and continue, even though this is a new disk
We’ll then wait for the installation to complete, at which point we then need to reboot the VM as advised
reboot
By default, the VM should boot from the hard drive rather than the CD, but an easy way to tell is that when you login as root, this time you’ll be asked for a password. In addition, the hostname will be want you entered during the installation
Although an ISO image that was just downloaded should be fairly new, we should still make sure everything is up to date
First we’ll update the package information
apk update
If you ever do a major upgrade it’s suggested to upgrade the package manager itself first, so as an example we’ll do that
apk add --upgrade apk-tools
apk add -u apk-tools
Then we’ll upgrade the rest of the software
apk upgrade --available
The –available option forces all packages to be upgraded
Alpine can keep a cache of installed packages on the local disk and the documentation recommends that you synchronise this
sync
We no longer need the CD/DVD drive so first we’ll shut down the VM
poweroff
Now, click on the Hardware section
Select the CD/DVD Drive for this VM and click Remove then click Yes to confirm
Then power this VM back up and login as root again
Remote Access:
At this stage we only have the OS installed and we don’t have access to copying and pasting in the console window
In which case, we’ll setup remote access to the VM via SSH
Now, we only have the root account on this computer, and although it isn’t advised to use that for remote logins, that’s what we’ll be doing as part of this setup process
In which case, it’s best to restrict SSH access to the VM
But the first thing we’re going to do is to install nano
apk add nano
It’s up to you, but for me, vi makes very simple things more complicated than they need to be
Next, we need to edit the repositories file
nano /etc/apk/repositories
We want to allow access to the community repository so delete the # on that line to uncomment it
Now save and exit
Next, we need to update the package information
apk update
Then we’ll install ufw as it provides a simpler frontend for setting up firewall rules
apk add ufw
What we want to do is to only allow SSH access and only from necessary devices
ufw limit proto tcp from 192.168.200.10 to any port 22
We use the limit option in case there’s a device trying to guess login credentials. After a few failed attempts that computer will be blocked from being able to access this one, or at least for a while
The source IP address could be a network although in this case I’ve restricted it to my management computer. You’ll want to change this to whatever is relevant to you
This VM has only one vNIC and it’s using DHCP. We don’t know the IP addresses of future VMs either, so that’s why the destination is set to any
Finally, for SSH the protocol is TCP and the destination port is 22
For this to take effect we need to enable ufw and make sure it starts at boot
ufw enable
rc-update add ufw
NOTE: Updating openrc is necessary on Alpine otherwise ufw won’t start on the next boot, even though the response from the ufw enable command suggests it will
Now we’ll double check that ufw is working and our rule is applied
ufw status
The default behaviour of firewalls is to implicitly drop all other traffic so it should now only allow SSH access and only from where we’ve allowed it
So now, although we’ll be allowing remote root logins, at least this will be restricted to a trusted computer
We now need to allow root login via SSH and there are various ways to do this
The best strategy to modify most config files like this is to add your own override files, rather than modifying the original config file
This is because changes can be introduced to the main file, especially after major updates, and then you’ll have to apply your modifications all over again
By using override files, you can allow the main file to be overwritten by the developer and your own preferences will remain intact
In which case, we’re going to create a new file by doing this
echo 'PermitRootLogin yes' > /etc/ssh/sshd_config.d/permitroot.conf
You can call the file something else, but it has to have an extension of .conf to be included
By adding that file, we’re allowing the root user to login remotely through SSH
First let’s check the file is correct
cat /etc/ssh/sshd_config.d/permitroot.conf
For this to take affect we need to restart the sshd service
service sshd restart
As I’m using DHCP I need to know the IP address of this VM
ip a
Now we should be able to SSH in as root with password authentication, for example
ssh root@192.168.100.20
TIP: If you can’t login, check what methods are being offered by enabling verbose mode
ssh -v root@192.168.100.20
Customisation:
If you’re going to create VMs by cloning an existing one, it makes sense to customise the original one first
This will save you having to repeat the same changes over and over again for every new VM
In which case we’ll install some additional packages
apk add cloud-init util-linux sudo openssh-server-pam e2fsprogs-extra qemu-guest-agent
The cloud-init package allows us to prepare the VM for use with cloud-init
For PVE, we’ll mount the cloud-init config file using an IDE drive, so we also need the util-linux package
Most, if not all of my computers are Debian based and I want to keep things consistent in Ansible, so I’ll install sudo
In the notes, there’s a mention that cloud-init can cause SSH login problems, in which case we’ll also add the openssh-server-pam package
Typically you’ll want to resize the disk of each new VM, but even if you don’t, I’ve noticed cloud-init generates an error relating to resizefs. For an EXT partition, like this VM has, we need to install the e2fsprogs-extra package
As we’re using PVE we’ll also install the qemu-guest agent
We’ll now enable the qemu-guest agent, as we want this to be running all the time
rc-update add qemu-guest-agent
And then we’ll start it
service qemu-guest-agent start
If you check the GUI, you should see in the Summary section of the VM an IPv4 and probably IPv6 address appear which indicates that PVE can now communicate with the guest agent
Now we’ll make another change to sshd, by adding another override file
echo 'UsePAM yes' > /etc/ssh/sshd_config.d/usepam.conf
As before, we need to enable PAM to avoid SSH login problems
For this to take affect we need to restart the sshd service
service sshd restart
Usually this doesn’t drop existing SSH sessions
Feel free to add additional packages that will be common to the VMs you’ll clone from this one
Fail2Ban for instance is a useful way to improve security
And although Debian 13 will phase out ntp in favour of ntpsec, I still prefer to use Chrony as it supports NTS that Cloudflare uses
Personally, though I save software maintenance and configuration for Ansible as it’s an ongoing task that can be better handled through automation
So this basic setup is enough for me
Enable Cloud-Init:
As useful as cloning is, enabling cloud-init brings some additional benefits
For instance, it can change the hostname for you and create a user account with elevated privileges
Before we do anything else though, take a snapshot of the VM though the GUI
This is very important because cloud-init is a one way process
For one thing, we need to do some testing, and having a snapshot will allow us to roll things back to just before cloud-init was enabled
But there’s still some final work to do on this work VM before it becomes our Alpine template
With a snapshot ready, we’ll run the cloud-init software to prepare the computer
setup-cloud-init
Now we need to override the default datasource that cloud-init will use when the VM boots up
echo "datasource_list: ['NoCloud']" > /etc/cloud/cloud.cfg.d/02-datasource.cfg
As before, PVE uses an IDE drive to present the cloud-init config on
All we need to use is the NoCloud option which basically means local provisioning
Now typically, cloud-init images are intended for cloud service providers and there won’t be a monitor attached to such a computer
Although we could switch this display over to a serial console, we’re using Proxmox VE and to me this just adds extra work
Besides, PVE has a limit on how many serial consoles you can have open at once, so we’ll skip that
In which case, we’ll power off the VM
poweroff
Once it’s off, back in the GUI, select the VM and click Hardware
From the Add drop-down menu select CloudInit Drive, select the storage location and click Add
Now click Cloud-Init and edit the settings you want for future VMs
For instance you could add a common user account and password and/or supply an SSH public key for the user
Any new VM that’s cloned from this will then create that user account as part of the cloud-init process
What makes this method preferable, is you can change this on a per VM basis, because the settings won’t be applied until the new VM boots up for the first time
One thing of note is the IP Config setting
By default, PVE has this setup with a blank static address for both IPv4 and IPv6 and that will cause cloud-init to fail, if you don’t enter anything
So for this template VM we’ll change this setting to DHCP
Now, if you want a new VM to have a static IP address, then on the cloned VM, edit this setting BEFORE you power it on
Testing:
The next thing to do is to test if cloud-init works when we clone this VM
So in the GUI, select the VM then right-click and select Clone or from the More drop-down menu in the top right corner select Clone
Set the VM ID and name then click Clone
Once the VM is created, select it and change the Cloud-Init settings if necessary and/or change its hardware settings
We want to watch the progress, so select the Console section for this VM and then power it on by clicking Start or Start Now
Now I have seen warnings about not being able to find a module called cc_reset_rmc
Initially I struggled to find what this was for, but after doing some more searching it appears to be for a Resource Monitoring and Control subsystem for IBM systems
So we could disable this or just ignore it
There is a deprecation warning as well in the ouput but that’s something for the developers to address
If there is a significant problem though, cloud-init will report a failure at the end and you’ll see red asterisks instead of green ones on the left side
First thing to note is that the hostname should match the name we provided when we did the cloning
In contrast, we would have to edit the /etc/hosts and /etc/hostname files if we cloned a normal template
Next we’ll check we can login via the console
If you created a cloud-init user account then use that, otherwise use root
Now, a user account created with cloud-init should have sudo rights, and you can check that with this command
sudo -i
Bear in mind we aren’t prompted for a password which isn’t good for security
The reason being is there is a file created for the user account to grant sudo rights
cat /etc/sudoers.d/90-cloud-init-users
Basically it grants sudo rights for all commands and without the need for a password
This is something that also needs further attention
Also, bear in mind the user account will be a member of adm and wheel as you’ll see when we check with this command
groups david
Where david in this case is the user account I setup in cloud-init
That’s something else you’ll probably want to address as even if sudo rights are removed for this account, it’s still a member of these important groups
Next we’ll want to check UFW was started
ufw status
We also want to check SSH is working, so first we need to know the IP address if we’re using DHCP
ip a
If you setup a non-root account then try connecting through SSH using that, but also test again with the root account
Now if things haven’t gone to plan you’ll have to fix any issues on the original VM, one of the reasons why we took a snapshot
Because the install process goes by so quickly, you can find a lot of useful information in the log file
more /var/log/cloud-init.log
Once you’ve identified any issues, power the clone off then delete it
Next, revert back to the snapshot of the original VM and try and fix the issues that you found
Once again, take a snapshot, then pickup from the point of running the setup-cloud-init command in the previous chapter
Repeat this until you have a working clone
In our case, things seem fine so we’ll power off this test VM
poweroff
And then delete it
Finalise VM:
As we know the cloud-init process is working, now is the time to tidy up and finalise this VM before we start using it
First, revert the VM back to the snapshot taken before cloud-init was setup
Now login as root through SSH
This is the last opportunity to ensure the root account has a strong, complex password, so do that now unless you’ve already done that
passwd
Login as root using another SSH session to make sure the new password works
Assuming it does, then close that session
Being able to resolve a hostname without having to add the domain name is useful so we’ll update the DNS resolver
nano /etc/resolv.conf
Add a new line at the end such as
search homelab.lan
But replace homelab.lan with your own domain name
Now save and exit
The computer will now append that domain name to hostnames allowing the DNS server to find entries it can resolve
Allowing remote root login was only meant to be temporary so we need to disable that by deleting the override file
rm /etc/ssh/sshd_config.d/permitroot.conf
For this to take affect we need to restart the sshd service
service sshd restart
Now try logging in as root using another SSH session to double check that you can’t
To remedy the user account concerns I brought up earlier, we’ll change the cloud-init configuration
Rather than editing the main config file though, we’ll add another override file
nano /etc/cloud/cloud.cfg.d/03-user.cfg
system_info:
default_user:
groups: []
sudo: ["ALL=(ALL) ALL"]
By adding this file, the user won’t be added to other groups and while it will still have full sudo rights, a password will be required
Now that I know what the cc_reset_rmc module warning relates to I could just ignore it
But instead we’ll comment it out in the main config file
sed -i 's/ - reset_rmc/# - reset_rmc/' /etc/cloud/cloud.cfg
Now create a new snapshot as we’ll be running one final test
Next, run the cloud-init software
setup-cloud-init
Then add an our override for the datasource
echo "datasource_list: ['NoCloud']" > /etc/cloud/cloud.cfg.d/02-datasource.cfg
Now we’ll power off the VM
poweroff
Once it’s off, back in the GUI, select the VM and click Hardware
From the Add drop-down menu select CloudInit Drive, select the storage location and click Add
Now click Cloud-Init and edit the settings
As before, we’ll add a user account and password and set the IP Config settings to use DHCP
Final Test:
Hopefully this will be our final test but we need to double-check that everything works when we clone this VM
So in the GUI, select the VM then right-click and select Clone or from the More drop-down menu in the top right corner select Clone
Set the VM ID and name then click Clone
Once the VM is created, select the Console section for this new VM and then power it on by clicking Start or Start Now
This time we only expect to see a deprecated warning
Login using the cloud-init account
Again, test this has sudo rights, but this time we should be prompted for a password
sudo -i
We’ll also check the account only belongs to its own group
groups david
UFW should still work, but it’s best to check
ufw status
We also want to check SSH is working, so first we need to know the IP address if we’re using DHCP
ip a
We shouldn’t be able to login as root now, but we should be able to get access using the non-root account
In our case, things seem fine so we’ll power off this test VM
poweroff
And then delete it
Now for some, this might be all you’ll want to do
You have a VM which is cloud-init ready and if you need to update it you can roll it back to the previous snapshot, make your changes and update it
On the other hand, you may prefer to turn this into a template, which is what we’ll cover next
Or maybe you’d prefer to create a cloud-init image. If so, feel free to skip the next chapter
Create Template:
Templates are what a hypervisor admin will probably clone new VMs from
Their main appeal is that you can’t power on a Template
So to me, they’re a read-only virtual machine
Bascially, you can’t add or change the software of the original VM and so you can’t break a “golden” image
For me that’s fine as I install only what’s necessary and let Ansible take care of the rest
And whenever a major OS is released I create a new template anyway because a fresh OS installation is preferable to an upgraded one
A template also makes sense because cloud-init is a one way process
If you did power up this VM, cloud-init would kick in and then you’d run into future cloning issues
You can, however, still make some hardware changes to a template
Now bear in mind, for Proxmox VE, there is no option in the GUI to revert a template back to a VM
However, you can do this from the CLI
qm set <vmID> --template 0
Assuming you do want to turn this VM into a template you have to remove any snapshots applied to it first
Because if you do try to turn a VM with snapshots into a template PVE will just refuse
To do this, select the VM, then either right-click and select convert to template or click on the More drop-down menu and select Convert to template
Now click Yes to confirm
TIP: Once this has completed you may notice the icon next to the name has changed
Going forward, you can clone this Template just like you would a VM
Once a new VM is created, select that and make any necessary cloud-init or hardware changes BEFORE powering it on
Typically you might want to increase the hard disk size, add more vCPUs, more RAM, etc
Once the new VM has powered on and cloud-init has finished, you should test that it works as expected, so login with the non-root account
Now that cloud-init has done its job, we’ll disable it by creating this file
sudo touch /etc/cloud/cloud-init.disabled
All that’s needed is for this file to exist
It’s also a good idea to remove the cloud-init settings from the VM so they can’t be seen “over the shoulder”
First, shut down the VM
sudo poweroff
In the GUI, select the Cloud-Init section for the VM
Reset these back to their defaults
Now click on the Hardware section
Select the CloudInit Drive, click Remove and then click Yes to confirm
You can now power the VM back on and start using it
Create Cloud-Init Image:
As useful as templates are, I prefer to use cloud-init images and let Ansible automate everything
While Ansible could clone a template or VM, cloning multiple new virtual machines and then updating their settings individually is more complicated and takes longer
First, make sure that the VM/template is turned off
Now delete any existing snapshots, although I already did that in the previous chapter
For this method of cloning we’re only interested in the hard drive
In the GUI, select Datacenter and then click storage
Now make a note of the Path/Target for the storage the VM/Template hard drive is stored on
For instance, I have an NFS share and the paths shows as
/mnt/pve/VMS
On the other hand, the path for a VM stored on the local drive will be
/var/lib/vz
In this demo though, the storage for the VM is using ZFS and that stores files in chunks so I’ll have to migrate the hard drive first
To do that I’ll click on the VM then select the Hardware section
Next select the hard drive and from the Disk Action drop-down menu select Move Storage
I’ll then select the new storage location
Depending on what the storage is, you might be able to opt for a format of raw or qcow2
From what I’ve read, raw is better for performance
But it’s probably best to let the system decide, which it does by default
For instance, if you use raw on an NFS storage, you won’t be able to take snapshots of that VM
I do prefer to delete the source drive as to me it just wastes space, so I’ll select that
Finally click Move disk and wait for the process to complete
Now we want to get a copy of this VM’s hard drive
Bear in mind, for me this throws an error message when its trying to set file attributes and it only seems to happen with templates
I don’t get this error when it’s a VM and it doesn’t seem to cause a problem, so I’ll ignore this
To copy the file, first open a shell or SSH into the server that last ran the VM/template
Disk files are stored in the <path>/images/<VMID> folder so first we’ll check what file we need to copy for this VM/template which has an ID of 9002
ls -l /mnt/pve/VMS/images/9002
In this example, I’m interested in this file
base-9000-disk-0.qcow2
This is the hard drive of the template created in the previous chapter
Otherwise it would have looked more like this
vm-9000-disk-0.qcow2
We want a copy of this hard drive and for this demo I’ll store it in the home folder of root, although normally I’d upload it to the Ansible server
We’ll grab a copy of the file and rename it
cp /mnt/pve/VMS/images/9002/base-9002-disk-0.qcow2 my_nocloud-alpine-latest.qcow2
You can put more details in the name if you like but it’s easier for Ansible if the name stays the same
But that’s our cloud-init image ready for use
What I’ll do now is to manually go through the process of creating a new VM
But if you want to know how to create VMs using Ansible and cloud-init images, I’ve made another video about that
https://www.techtutorials.tv/sections/promox/proxmox-create-templates-quicker/
Back in the GUI, we’ll create a basic Linux VM with an ID of 700, without a CD/DVD drive, with the Qemu Agent enabled, without a hard drive, 1 vCPU of type Host, 2GB of RAM without Ballooning and a vNIC in the relevant VLAN
You can of course do this in the CLI if you prefer
Back in our shell or SSH session we’ll import a copy of the hard drive to the new VM
qm importdisk 700 my_nocloud-alpine-latest.qcow2 VMS --format qcow2
Where 700 is the VMID of the new VM and VMS is the storage name to add this to
The –format parameter is because we’re using a file in qcow2 format
Back in the GUI again, select the new VM then click the Hardware section
At the bottom of the list will be an unused disk drive
Select this, click Edit then click Add
From the Add drop down menu, select CloudInit Drive, select the storage location then click Add
Now click the Cloud-init section and update the relevant details
You’ll likely want to add a user account and password as a minimum but remember to update the IP Config settings or cloud-init will fail if it doesn’t have an IP address
Click the Options section, select Boot Order then click Edit
Enable the scsi0 drive then drag it to the top of the list so that the VM boots from the hard drive
Now click OK
We’ll check the progress for this VM, so select the Console section and then click Start or Start Now
What we should see is the same cloud-init process as before
Once the new VM has powered on and cloud-init has finished, you should test that it works as expected
Now that cloud-init has done its job for this VM, as I mentioned in the previous chapter, I prefer to disable it
touch /etc/cloud/cloud-init.disabled
All that’s needed is for this file to exist
It’s also a good idea to remove the cloud-init settings from the VM so they can’t be seen “over the shoulder”
First, shut down the VM
poweroff
In the GUI, select the Cloud-Init section for the VM
Reset these back to their defaults
Now click on the Hardware section
Select the CloudInit Drive, click Remove and then click Yes to confirm
You can now power the VM back on and start using it
Now although this may seem like a slower method than just cloning from a Template, Ansible will do this much quicker, particularly when creating several VMs
Summary:
I must admit, the process for creating an Alpine cloud-init image was rather lengthy and I found that it was prone to errors
It actually took me quite a while to fix various problems along the way, but in the end I now have an image that’s ready
As per Proxmox’s documentation though, creating your own image is a safer method
In any case, what I have now is a more slimline OS that is quicker to boot and has a smaller attack surface
Best of all, this allows me to take advantage of newer versions of packages such as Podman
Sharing is caring!