Creating golden image for Proxmox with cloud-init and Packer

Creating an image

I’m trying to create golden image for AlmaLinux with Packer which would support Proxmox cloud-init (NoCloud option).

Ton’s of tutorials available for Ubuntu, but lack of tutorial for rpm based distro.

So here is my almalinux.pkr.hcl:

# AlmaLinux
# ---
# Packer Template to create an Almalinux Server with Docker on Proxmox

# Install proxmox builder
# packer plugins install github.com/hashicorp/proxmox

# Variable Definitions 
# Variable Definitions is set via ENV VAR
# EXPORT PROXMOX_USERNAME
# EXPORT PROXMOX_TOKEN
# EXPORT PROXMOX_URL

# Variable Definitions is set via ENV VAR
variable "proxmox_api_url" {
    type = string
}

variable "proxmox_api_token_id" {
    type = string
}

variable "proxmox_api_token_secret" {
    type = string
    sensitive = true
}

# Resource Definiation for the VM Template
source "proxmox-iso" "almalinux-server-docker" {

    # PACKER Autoinstall Settings
    http_directory = "http" 
    
    boot_command = ["<esc><wait>", "vmlinuz initrd=initrd.img inst.geoloc=0 rd.driver.blacklist=dm-multipath net.ifnames=0 biosdevname=0 ", "ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/kickstart.cfg", "<enter>"]
    boot_wait    = "10s"

    # Proxmox Connection Settings
    proxmox_url = "${var.proxmox_api_url}"
    username = "${var.proxmox_api_token_id}"
    token = "${var.proxmox_api_token_secret}"
    # (Optional) Skip TLS Verification
    insecure_skip_tls_verify = true
    
    # VM General Settings
    node = "pve"
    vm_id = "8002"
    vm_name = "almalinux-server-docker"
    template_description = "Almalinux Image with Docker pre-installed"
    ssh_username = "root"
    ssh_password = "root"
    ssh_timeout = "20m"

    # VM OS Settings
    # (Option 1) Local ISO File
    iso_file = "local:iso/AlmaLinux-8-latest-x86_64-dvd.iso"
    # - or -
    # (Option 2) Download ISO
    # iso_url = "https://releases.ubuntu.com/.../ubuntu-22.04-live-server-amd64.iso"
    # iso_checksum = "f8e3086f3cea0fb3fefb29937ab5ed9d19e767079633960ccb50e76153effc98"
    iso_storage_pool = "local"
    unmount_iso = true

    # VM System Settings
    qemu_agent = true

    # VM Hard Disk Settings
    scsi_controller = "virtio-scsi-pci"

    disks {
        disk_size = "20G"
        format = "raw"
        storage_pool = "local-lvm"
        storage_pool_type = "lvm"
        type = "virtio"
    }

    # VM CPU Settings
    cores = "1"
    
    # VM Memory Settings
    memory = "2048" 

    # VM Network Settings
    network_adapters {
        model = "virtio"
        bridge = "vmbr0"
        firewall = "true"
   #    vlan_tag =  "50"
    } 

    # VM Cloud-Init Settings
    cloud_init = true
    cloud_init_storage_pool = "local-lvm"
}

# Build Definition to create the VM Template
build {
    name = "almalinux-server-docker"
    sources = ["source.proxmox-iso.almalinux-server-docker"]

    provisioner "shell" {
        inline = [
            "sleep 30",
            "echo 'Remove temporary cloud-init files'",
            "rm -f /etc/cloud/cloud.cfg.d/05_logging.cfg",
            "rm -f /etc/cloud/cloud.cfg.d/99_cleanup.cfg",
            "rm -rf /var/lib/cloud/instances/*",
            "echo 'Remove SSH host keys'",
            "rm -f /etc/ssh/ssh_host_*",
            "echo 'Remove Packer SSH key'",
            "rm -f /root/.ssh/authorized_keys",
            "systemctl enable sshd",
            "echo 'Clean package cache'",
            "dnf clean all",
            "mkdir -p /var/lib/cloud/instance/ "
            
        ]
    }

    provisioner "file" {
        source      = "cloud-init.cfg"
        destination = "/var/lib/cloud/instance/cloud-init.cfg"
    }

    provisioner "shell" {
        inline = [
            "echo 'Checking cloud-init configuration'",
            "cloud-init schema --config-file /var/lib/cloud/instance/cloud-init.cfg"
            
        ]
    }
}

kickstart.cfg:

lang en_US
keyboard --vckeymap=us --xlayouts='us'
timezone Europe/Warsaw --isUtc
#root passwrod is root
rootpw $1$random_s$E0GWrlXVjpmiQczaTXyXq/ --iscrypted
#platform x86, AMD64, or Intel EM64T
reboot
text
cdrom
bootloader --location=mbr --append="rhgb quiet crashkernel=auto"
zerombr
clearpart --all --initlabel
autopart
auth --passalgo=sha512 --useshadow
#password for almauser-proxomx is almauser
user --name=almauser-proxmox --password=$6$8v4lYU0pIayoWR0G$MTNdTtiH/Er1zVU.ISdgtqEQIKlJGMds3D8BzIZmFjU4oEiRJkjzsR3/vVoH53.xul6DTPXNv8pSklsWGcqgj1
selinux --disabled
firewall --disabled
skipx
firstboot --disable
%post
usermod -aG wheel almauser-proxmox
dnf install cloud-init -y
%end
%packages
%end

cloud-init.cfg:

#cloud-config
user-data:
  hostname: my-almalinux-instance
  users:
    - name: almalinux-user
      sudo: ALL=(ALL) NOPASSWD:ALL
      groups: users, wheel
      ssh_authorized_keys:
        - ssh-rsa somerandompublickkeyishereAAAAABBBBBCCCCCDDDDD OpenSSH-rsa-import-061922

  packages:
    - mc

Command to build image:

packer build -var-file=./credentials.pkr.hcl ./almalinux.pkr.hcl

I’ve got almalinux-server-docker template in Proxmox.

Then I cloned template to a new VM instance and started.

According to boot logs cloud-init is not configuring the system. Also the hostname of a system is not the same as I chose during Clone VM template wizard.

What’s my aim:
I want to create a template for AlmaLinux in Proxmox. The template should automatically set the hostname when cloning through the VM template wizard and make some initial configurations during the first system boot.

Links

https://pve.proxmox.com/wiki/Cloud-Init_Support

I think I found a mistake.

This line in almalinux.pkr.hcl: is incorrect:

"mkdir -p /var/lib/cloud/instance/ "

According to FAQ — cloud-init 21.3 documentation

The /var/lib/cloud/instance directory is a symbolic link that points to the most recenlty used instance-id directory.

Also I added this line to kickstart.cfg:

sshkey --username=almauser-proxmox

So the final content of files are:
almalinux.pkr.hcl:

# AlmaLinux
# ---
# Packer Template to create an Almalinux Server with Docker on Proxmox

# Install proxmox builder
# packer plugins install github.com/hashicorp/proxmox

# Variable Definitions 
# Variable Definitions is set via ENV VAR
# EXPORT PROXMOX_USERNAME
# EXPORT PROXMOX_TOKEN
# EXPORT PROXMOX_URL

# Variable Definitions is set via ENV VAR
variable "proxmox_api_url" {
    type = string
}

variable "proxmox_api_token_id" {
    type = string
}

variable "proxmox_api_token_secret" {
    type = string
    sensitive = true
}

# Resource Definiation for the VM Template
source "proxmox-iso" "almalinux-server-docker" {

    # PACKER Autoinstall Settings
    http_directory = "http" 
    
    boot_command = ["<esc><wait>", "vmlinuz initrd=initrd.img inst.geoloc=0 rd.driver.blacklist=dm-multipath net.ifnames=0 biosdevname=0 ", "ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/kickstart.cfg", "<enter>"]
    boot_wait    = "10s"

    # Proxmox Connection Settings
    proxmox_url = "${var.proxmox_api_url}"
    username = "${var.proxmox_api_token_id}"
    token = "${var.proxmox_api_token_secret}"
    # (Optional) Skip TLS Verification
    insecure_skip_tls_verify = true
    
    # VM General Settings
    node = "pve"
    vm_id = "8002"
    vm_name = "almalinux-server-docker"
    template_description = "Almalinux Image with Docker pre-installed"
    ssh_username = "root"
    ssh_password = "root"
    ssh_timeout = "20m"

    # VM OS Settings
    # (Option 1) Local ISO File
    iso_file = "local:iso/AlmaLinux-8-latest-x86_64-dvd.iso"
    # - or -
    # (Option 2) Download ISO
    # iso_url = "https://releases.ubuntu.com/.../ubuntu-22.04-live-server-amd64.iso"
    # iso_checksum = "f8e3086f3cea0fb3fefb29937ab5ed9d19e767079633960ccb50e76153effc98"
    iso_storage_pool = "local"
    unmount_iso = true

    # VM System Settings
    qemu_agent = true

    # VM Hard Disk Settings
    scsi_controller = "virtio-scsi-pci"

    disks {
        disk_size = "20G"
        format = "raw"
        storage_pool = "local-lvm"
        storage_pool_type = "lvm"
        type = "virtio"
    }

    # VM CPU Settings
    cores = "1"
    
    # VM Memory Settings
    memory = "2048" 

    # VM Network Settings
    network_adapters {
        model = "virtio"
        bridge = "vmbr0"
        firewall = "true"
   #    vlan_tag =  "50"
    } 

    # VM Cloud-Init Settings
    cloud_init = true
    cloud_init_storage_pool = "local-lvm"
}

# Build Definition to create the VM Template
build {
    name = "almalinux-server-docker"
    sources = ["source.proxmox-iso.almalinux-server-docker"]

    provisioner "shell" {
        inline = [
            "sleep 30",
            "echo 'Remove temporary cloud-init files'",
            "rm -f /etc/cloud/cloud.cfg.d/05_logging.cfg",
            "rm -f /etc/cloud/cloud.cfg.d/99_cleanup.cfg",
            "rm -rf /var/lib/cloud/instances/*",
            "echo 'Remove SSH host keys'",
            "rm -f /etc/ssh/ssh_host_*",
            "echo 'Remove Packer SSH key'",
            "rm -f /root/.ssh/authorized_keys",
            "systemctl enable sshd",
            "echo 'Clean package cache'",
            "dnf clean all"
            
            
        ]
    }

    provisioner "file" {
        source      = "cloud-init.cfg"
        destination = "/tmp/cloud-init.cfg"
    }

    provisioner "shell" {
        inline = [
            "echo 'Applying cloud-init configuration'",
            "cloud-init schema --config-file /tmp/cloud-init.cfg"
            
        ]
    }
}

kickstart.cfg:

lang en_US
keyboard --vckeymap=us --xlayouts='us'
timezone Europe/Warsaw --isUtc
#root passwrod is root
rootpw $1$random_s$E0GWrlXVjpmiQczaTXyXq/ --iscrypted
#platform x86, AMD64, or Intel EM64T
reboot
text
cdrom
bootloader --location=mbr --append="rhgb quiet crashkernel=auto"
zerombr
clearpart --all --initlabel
autopart
auth --passalgo=sha512 --useshadow
#password for almauser-proxomx is almauser
user --name=almauser-proxmox --password=$6$8v4lYU0pIayoWR0G$MTNdTtiH/Er1zVU.ISdgtqEQIKlJGMds3D8BzIZmFjU4oEiRJkjzsR3/vVoH53.xul6DTPXNv8pSklsWGcqgj1
sshkey --username=almauser-proxmox "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqOzstlYjfoqX+sGRW0qH8IGUeySxpLYJrs4Pss3UudDTQ9j6WXktyFuWrMRBZyvmtYSAQV/KtoWhgTirVUocBhrqzM+IOZxQ8CfyOm6uFDIEGMj872ZJUgwCXR+dYe3xT9S+LqqTKP1uO5bWvWGCFhVlXTIZdagz/RkhOwItY1jMINwmot1Zl0hpYhM8hLPgBHVipsE7qtovtWp1JryELvRJF/Hv86Pm/i1cktRVv+3VvrItX4yLukmusRD2hNShmREBRIdmTVj+d8Ex/d2vA/YX1PwAwy8gRMIjneiTHnp7zflZogSKIUqsQt3Qrkfy3kJxARZBUXzixZNvhKgSJ OpenSSH-rsa-import-061922"
selinux --disabled
firewall --disabled
skipx
firstboot --disable
%post
usermod -aG wheel almauser-proxmox
dnf install cloud-init -y
%end
%packages
%end

cloud-init.cfg:

#cloud-config
user-data:
  hostname: my-almalinux-instance
  users:
    - name: almalinux-user
      sudo: ALL=(ALL) NOPASSWD:ALL
      groups: users, wheel
      ssh_authorized_keys:
        - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqOzstlYjfoqX+sGRW0qH8IGUeySxpLYJrs4Pss3UudDTQ9j6WXktyFuWrMRBZyvmtYSAQV/KtoWhgTirVUocBhrqzM+IOZxQ8CfyOm6uFDIEGMj872ZJUgwCXR+dYe3xT9S+LqqTKP1uO5bWvWGCFhVlXTIZdagz/RkhOwItY1jMINwmot1Zl0hpYhM8hLPgBHVipsE7qtovtWp1JryELvRJF/Hv86Pm/i1cktRVv+3VvrItX4yLukmusRD2hNShmREBRIdmTVj+d8Ex/d2vA/YX1PwAwy8gRMIjneiTHnp7zflZogSKIUqsQt3Qrkfy3kJxARZBUXzixZNvhKgSJ OpenSSH-rsa-import-061922

  packages:
    - mc

But the problem is still here.
How to pass content of cloud-init.cfg to the Proxmox cloud-init disk ?