0

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?

0 Answers0