I'm running Proxmox in my home lab and I want to create a golden template image with docker preinstalled so I can easily clone the template and spawn a new VM in a few minutes.
After building a custom Cloud-init image to use in my homelab I noticed that It does not set the static IPv4 that I've assigned to it. It seems that It only applies it after the VM reboots.
I'm automating the whole process with Terraform and Packer.
This is my Packer file for the template: ubuntu-server-jammy-jellyfish-docker.pkr.hcl:
variable "proxmox_api_url" {
type = string
}
variable "proxmox_api_token_id" {
type = string
}
variable "proxmox_api_token_secret" {
type = string
sensitive = true
}
# Resource Definition for the VM Template
source "proxmox" "ubuntu-server-jammy-jellyfish-docker-drcarmen-hv" {
# Proxmox Connection Settings
proxmox_url = "${var.proxmox_api_url}"
username = "${var.proxmox_api_token_id}"
token = "${var.proxmox_api_token_secret}"
insecure_skip_tls_verify = true
# VM General Settings
node = "ahv02"
vm_id = "500"
vm_name = "ubuntu-server-jammy-jellyfish-docker"
template_description = "Ubuntu Server Jammy Jellyfish Image with Docker Installed"
# VM OS Settings
# (Option 1) Local ISO File
iso_file = "nas-nfs:iso/ubuntu-22.04.1-live-server-amd64.iso"
# - or -
# (Option 2) Download ISO
# iso_url = "https://releases.ubuntu.com/22.04/ubuntu-22.04.1-live-server-amd64.iso"
# iso_checksum = "10f19c5b2b8d6db711582e0e27f5116296c34fe4b313ba45f9b201a5007056cb"
iso_storage_pool = "nas-nfs"
unmount_iso = true
# VM System Settings
qemu_agent = true
# VM Hard Disk Settings
scsi_controller = "virtio-scsi-pci"
disks {
disk_size = "20G"
format = "qcow2"
storage_pool = "nas-nfs"
storage_pool_type = "nfs"
type = "virtio"
}
# VM CPU Settings
cores = "1"
# VM Memory Settings
memory = "2048"
#VM Network Settings
network_adapters {
model = "virtio"
bridge = "vmbr0"
firewall = "false"
}
# VM Cloud-Init Settings
cloud_init = true
cloud_init_storage_pool = "nas-nfs"
# PACKER Boot Commands
boot_command = [
"<esc><wait>",
"e<wait>",
"<down><down><down><end>",
"<bs><bs><bs><bs><wait>",
"autoinstall ds=nocloud-net\\;s=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ ---<wait>",
"<f10><wait>"
]
boot = "c"
boot_wait = "5s"
# PACKER Auto-Install Settings
http_directory = "http"
# (Optional Bind IP Address and Port
# http_bind_address = "0.0.0.0"
# http_port_min = 8802
# http_port_max = 8802
http_interface = "tun0"
ssh_username = "orion"
# (Option 1) Add your password here
# ssh_password = "your-password"
# - or -
# (Option 2) Add your Private SSH Key file here
ssh_private_key_file = "../../../keys/id_ed25519"
# Raise the timeout, when installation takes longer
ssh_timeout = "20m"
}
# Build Definition to create the VM Template
build {
name = "ubuntu-server-jammy-jellyfish-docker"
sources = ["source.proxmox.ubuntu-server-jammy-jellyfish-docker-drcarmen-hv"]
# Provision the VM Template for Cloud-Init Integration in Proxmox #1
provisioner "shell" {
inline = [
"while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 1; done",
"sudo rm /etc/ssh/ssh_host_*",
"sudo truncate -s 0 /etc/machine-id",
"sudo apt -y autoremove --purge",
"sudo apt -y clean",
"sudo apt -y autoclean",
"sudo cloud-init clean",
"sudo rm -f /etc/cloud/cloud.cfg.d/subiquity-disable-cloudinit-networking.cfg",
"sudo sync"
]
}
# Provisioning the VM Template for Cloud-Init Integration in Proxmox #2
provisioner "file" {
source = "../../files/99-pve.cfg"
destination = "/tmp/99-pve.cfg"
}
#Provisioning the VM Template for Cloud-Init Integration in Proxmox #3
provisioner "shell" {
inline = [ "sudo cp /tmp/99-pve.cfg /etc/cloud/cloud.cfg.d/99-pve.cfg" ]
}
#Provisioning the VM Template with Docker Installation #4
provisioner "shell" {
inline = [
"sudo apt-get install -y ca-certificates curl gnupg lsb-release",
"curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg",
"echo \"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null",
"sudo apt-get -y update",
"sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin"
]
}
}
and the asociated user-data
file:
#cloud-config
autoinstall:
version: 1
locale: en_US
keyboard:
layout: us
ssh:
install-server: true
allow-pw: true
disable_root: true
ssh_quiet_keygen: true
allow_public_ssh_keys: true
packages:
- qemu-guest-agent
- sudo
storage:
layout:
name: direct
swap:
size: 0
user-data:
package_upgrade: false
timezone: Europe/Bucharest
users:
- name: orion
groups: [adm, sudo]
lock-passwd: false
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
# passwd: your-password
# - or -
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtz6qiFn+YS6IcG8OciQA/3UMhKTN04CVssHBV03f/L Jenkins - CI/CD
power:
mode: reboot
I already tried to get the IP from the VM when I create it and then use that IP to ssh in and reboot the VM but that seems like a hack rather then a solution.
Do you have any ideas as what might cause the IP not to assign when the cloud-init initializes the VM and how to debug this and fix it?