I recently began to set up a new MiniPC cluster and needed a VM template. Usually, I would use something like Ubuntu. However, this time I wanted to go with Debian. Initially, my older methods of using Packer
seemed to offer little for this process. Though I was looking half-heartedly. Then along came Brandon’s post on his deployment of Debian 11
.
Brandon’s method seemed solid, but it had a few issues for my work case:
- Debian 11 and not Debian 12.
- Instructions weren’t 100% clear.
- I wanted
Trim
on the main storage. - I wanted to set
Start On Boot
. - Disk Size was set to
2GB
by default.
Initial Steps
Let’s first login to your Proxmox server running something newer, such as versions 7 or 8
.
Once logged in, open up the shell
inside of your desired deployment server.
At this point, you should be greeted by a BASH
prompt as root@<YourServersName>
.
First, let’s head to the tmp directory by running cd /tmp
.
Secondly, we need to download the image from Debian’s cloud image website. You can select whichever version you Debian you would like but I would suggest Bookworm
as it is the current latest.
After deciding the version you will be using. Select the latest build and find the file named debian-<version>-genericcloud-amd64-<date>.qcow2
. For me as of this writing that is debian-12-genericcloud-amd64-20240507-1740.qcow2
. Copy the link to that file, and we will use it to download to our tmp
directory. To do that, run wget https://cloud.debian.org/images/cloud/bookworm/20240507-1740/debian-12-genericcloud-amd64-20240507-1740.qcow2
Summary:
# Change to tmp directory to keep things clean.
cd /tmp
# Download image from debian's website.
wget https://cloud.debian.org/images/cloud/bookworm/20240507-1740/debian-12-genericcloud-amd64-20240507-1740.qcow2
Initial VM Creation
Now that we have downloaded the Debian image, we need to create an actual VM.
First, we need to create a VM. For my documentation, I am going to use the VMID of 900
but you can change this to whatever you like.
qm create 900 --name Debian12CI --net0 virtio,bridge=vmbr0
Values:
- 900 = VMID
- Debian12CI = VM Name, and will transition to your Template name.
- virtio = network type, Virtio is the suggested method here.
- vmbr0 = The name of your network bridge in Proxmox. Default is:
vmbr0
.
Secondly, we need to import the disk we downloaded from earlier.Make sure to use the name of the file you downloaded.
qm importdisk 900 debian-12-genericcloud-amd64-20240507-1740.qcow2 local-lvm
Values:
- 900 = VMID
- debian-12-genericcloud-amd64-20240507-1740.qcow2 = Name of the image we downloaded from Debian’s website. You can find the version you downloaded with
ls /tmp
. - local-lvm = Storage location on your server. This could also be something like
local-zfs
.
Now let’s make it so we can mount the disk we just created.
qm set 900 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-900-disk-0,discard=on
Values:
- 900 = VMID
- virtio-scsi-pci = VMs host bus adapter for talking to your virtual drives.
local-lvm:vm-900-disk-0
= The default disk created by our previous command along with the storage location.discard=on
= Enable VM Trimming of disk to conserve space (Thin Provision).
Now we need to create a Cloud-Init
drive! It’s why we are here after all!
qm set 900 --ide2 local-lvm:cloudinit
Values:
- 900 = VMID
- local-lvm = storage location.
- cloudinit = cloudinit drive location, this shouldn’t be changed.
Let’s set our default boot drive.
qm set 900 --boot c --bootdisk scsi0
Values:
- 900 = VMID
- scsi0 = id of the drive we created two steps ago.
This step is very much Optional
but we can set up a serial terminal instead of a graphical one. To do this, run the following command.
qm set 900 --serial0 socket --vga serial0
Values:
- 900 = VMID
- –serial0 = Creates a serial interface.
- socket = Specifies the type of serial connection.
- –vga = We are setting the VM shell method on
serial0
.
To make it so our Proxmox node and VM can do some light communication let’s set up the agent
utility. To make this work, you will need to manually install qemu-guest-agent
inside of your VM after it is created.
qm set 900 --agent enabled=1
Values:
- 900 = VMID
--agent enabled=1
= Enabling the agent option on the VM config.
Summary:
# Create VM.
qm create 900 --name Debian12CI --net0 virtio,bridge=vmbr0
# Import the image we previously downloaded to an virtual disk.
qm importdisk 900 debian-12-genericcloud-amd64-20240507-1740.qcow2 local-lvm
# Attach the virtual disk to our VM.
qm set 900 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-900-disk-0,discard=on
# Add the cloud-init drive.
qm set 900 --ide2 local-lvm:cloudinit
# Set our boot drive.
qm set 900 --boot c --bootdisk scsi0
# Use a serial console.
qm set 900 --serial0 socket --vga serial0
# Enable the agent.
qm set 900 --agent enabled=1
At this point, we now have a functional VM. At this point in the original documentation we would convert this into a Template and be on our way. However, I want to add a few more edits.
Customization
I want my new templates to already have the onboot
flag set. We can do that with the following command.
qm set 900 --onboot 1
Values:
- 900 = VMID
--onboot 0
= Disabled Autostart--onboot 1
= Enabled Autostart
Since we made this VM from scratch it doesn’t have some other customizations. Let’s inform our system that it is running a 2.6+ linux kernel.
qm set 900 --ostype l26
Values:
- 900 = VMID
- l26 = Linux 6.x - 2.6 Kernel. (Moden Linux Kernels):
l24, l26, other, solaris, w2k, w2k3, w2k8, win10, win11, win7, win8, wvista, wxp
Let’s give ourselves some more space by increasing the default disk size to something more comfortable.
qm resize 900 scsi0 +30G
Values:
- 900 = VMID
local-lvm:vm-900-disk-0
= Our file path to the virtual disk.- 30 = Increase by
30GB
of storage. Should end up around32GB
.
Let’s increase the default memory to 2GB.
qm set 900 --memory 2048
Values:
- 900 = VMID
--memory 2048
= Memory in MBs. 2048 = 2GB, 4096 = 4GB, 8192 = 8GB.
Summary:
# Set to autoboot.
qm set 900 --onboot 1
# Set the OS Type to Linux 2.6 +
qm set 900 --ostype l26
# Resize the storage
qm resize 900 scsi0 +30G
# Increase Memory
qm set 900 --memory 2048
Template Time!
We need to transition this into a template, which is pretty easy! Simply run: qm template 900
Summary:
# Change our VM into a template
qm template 900
Clone and Cloud-Init
Now when you are ready to deploy, head into Proxmox and either right-click then clone your template or run the following command: qm clone 900 901 --name cloned-vm
.
Afterward, head into your new VM and manually edit the Cloud-init
section of your VM. Make sure to set the: User, Password, DNS Servers, IP Config
settings or you are going to have a difficult time.
Next, head into the hardware
settings and confirm your needs are met for the VM you will be running. Take a look at Memory, CPU, Disk, and Network
settings.
After that, head into options
and brush up any final things before starting your VM.
At this point, you can right-click and start your new VM.
Happy Proxmoxing!
Extra:
Here is a look at my setup.
# Change to tmp directory to keep things clean.
cd /tmp
# Download image from debian's website.
wget https://cloud.debian.org/images/cloud/bookworm/20240507-1740/debian-12-genericcloud-amd64-20240507-1740.qcow2
# Create VM.
qm create 900 --name Debian12CI --net0 virtio,bridge=insecure
# Import the image we previously downloaded to an virtual disk.
qm importdisk 900 debian-12-genericcloud-amd64-20240507-1740.qcow2 local-lvm
# Attach the virtual disk to our VM.
qm set 900 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-900-disk-0,discard=on
# Add the cloud-init drive.
qm set 900 --ide2 local-lvm:cloudinit
# Set our boot drive.
qm set 900 --boot c --bootdisk scsi0
# Use a serial console.
qm set 900 --serial0 socket --vga serial0
# Enable the agent.
qm set 900 --agent enabled=1
# Set to autoboot.
qm set 900 --onboot 1
# Set the OS Type to Linux 2.6 +
qm set 900 --ostype l26
# Resize the storage
qm resize 900 scsi0 +254G
# Increase Memory
qm set 900 --memory 8192
# Increase CPU Count and makes them more migratable.
qm set 900 --cpu cputype=x86-64-v4 --cores 4 --sockets 1
You can find out your supported cputype by the following script modified from David Yin’s Blog.
#!/bin/sh -eu
flags=$(cat /proc/cpuinfo | grep flags | head -n 1 | cut -d: -f2)
supports_v2='awk "/cx16/&&/lahf/&&/popcnt/&&/sse4_1/&&/sse4_2/&&/ssse3/ {found=1} END {exit !found}"'
supports_v2_aes='awk "/aes/ {found=1} END {exit !found}"'
supports_v3='awk "/avx/&&/avx2/&&/bmi1/&&/bmi2/&&/f16c/&&/fma/&&/abm/&&/movbe/&&/xsave/ {found=1} END {exit !found}"'
supports_v4='awk "/avx512f/&&/avx512bw/&&/avx512cd/&&/avx512dq/&&/avx512vl/ {found=1} END {exit !found}"'
echo "$flags" | eval $supports_v2 || exit 2 && echo "CPU supports x86-64-v2"
echo "$flags" | eval $supports_v2_aes || exit 2 && echo "CPU supports x86-64-v2-AES"
echo "$flags" | eval $supports_v3 || exit 3 && echo "CPU supports x86-64-v3"
echo "$flags" | eval $supports_v4 || exit 4 && echo "CPU supports x86-64-v4"