Skip to content

Artifactory Post-Processor

Type: artifactory

Artifact BuilderId: packer.post-processor.artifactory

The Packer Plugin for Artifactory is a post-processor (artifactory) that can be used with HashiCorp Packer to upload virtual machine artifacts to JFrog Artifactory.

Supported Platforms

This plugin supports the following platforms:

Platform Type Support
VMware vSphere Bare Metal Hypervisor Supported
VMware Fusion Desktop Hypervisor (macOS) Supported
VMware Workstation Desktop Hypervisor (Windows/Linux) Supported
Other Various Best Effort

Note

While the plugin may function with other platforms that generate OVA/OVF files, official testing and support are currently limited to the VMware by Broadcom ecosystem.

Supported Artifacts

The plugin supports the following artifacts:

  • OVA: .ova — A single compressed archive package containing all the supporting virtual machine files.
  • OVF: .ovf — An array of virtual machine files supporting an Open Virtualization Format package.

Configuration Reference

The following configuration options are available for the post-processor.

Required

  • url (string) — The base URL of the Artifactory instance (e.g., https://packages.example.com/artifactory).

  • repository (string) — The name of the repository to upload the artifact to.

  • artifact_name (string) — The name of the artifact being uploaded.

Optional

  • api_key (string) — An API key to authenticate to the Artifactory instance. Environment variable: ARTIFACTORY_API_KEY.

  • access_token (string) — An access token to authenticate to the Artifactory instance. Environment variable: ARTIFACTORY_TOKEN.

  • username (string) — A username to authenticate to the Artifactory instance. Environment variable: ARTIFACTORY_USERNAME.

  • password (string) — A password to authenticate to the Artifactory instance. Environment variable: ARTIFACTORY_PASSWORD.

  • artifact_path (string) — The path within the repository where the artifact will be stored.

  • artifact_path_properties (bool) — Whether to apply the properties to the path of the artifact in addition to each uploaded file. (default: false)

    Note

    Ignored if properties is empty.

    Note

    Ignored if the Artifactory instance does not support setting properties on the artifact's repository path. Uploaded files are unaffected by this restriction.

  • max_retries (int) — The number of retry attempts for failed uploads. (default: 3)

  • timeout_seconds (int) — The request timeout in seconds. (default: 30)

  • overwrite (*bool) — Whether to overwrite existing artifacts. (default: false)

    Note

    The upload will fail if the artifact already exists and the overwrite flag is set to false.

  • properties (map[string]string) — Custom properties to attach to artifacts.

  • additional_ovf_extensions ([]string) — Additional file extensions to upload alongside an OVF package, beyond the default set (.ovf, .mf, .vmdk, .cert, .vdi). Extensions may be given with or without a leading dot (e.g. nvram or .nvram).

Tip

Provide exactly one authentication method: API key, access token, or username and password (via configuration or environment variables).

Example Usage

Note

Complete examples for VMware vSphere and VMware desktop hypervisors are available in the repository examples directory. The files below are included from those examples.

Basic Authentication

Post-Processor Configuration
# Basic Authentication.

build {
  sources = [
    "source.vmware-iso.example",
    "source.vsphere-iso.example",
  ]

  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y open-vm-tools"
    ]
  }

  post-processor "artifactory" {
    url           = var.artifactory_url
    username      = var.artifactory_username
    password      = var.artifactory_password
    repository    = var.artifactory_repository
    artifact_name = local.artifact_name
    artifact_path = local.artifact_path
  }
}
Additional Configuration

Versions:

packer {
  required_plugins {
    artifactory = {
      version = ">= 0.1.0"
      source  = "github.com/tenthirtyam/artifactory"
    }
    vmware = {
      version = ">= 2.0.0"
      source  = "github.com/vmware/vmware"
    }
    vsphere = {
      version = ">= 2.0.0"
      source  = "github.com/vmware/vsphere"
    }
  }
}

Variables:

# ---------------------------------------------------------------------------
# Artifactory Basic Authentication
# ---------------------------------------------------------------------------

variable "artifactory_url" {
  type        = string
  description = "URL of the Artifactory instance to use for the build."
  default     = env("ARTIFACTORY_URL") != "" ? env("ARTIFACTORY_URL") : "http://localhost:8081/artifactory"
}

variable "artifactory_username" {
  type        = string
  description = "Username to authenticate to the Artifactory instance."
  default     = env("ARTIFACTORY_USERNAME") != "" ? env("ARTIFACTORY_USERNAME") : "admin"
  sensitive   = true
}

variable "artifactory_password" {
  type        = string
  description = "Password to authenticate to the Artifactory instance."
  default     = env("ARTIFACTORY_PASSWORD") != "" ? env("ARTIFACTORY_PASSWORD") : "password"
  sensitive   = true
}

variable "artifactory_repository" {
  type        = string
  description = "Repository in the Artifactory instance to use for the build."
  default     = env("ARTIFACTORY_REPOSITORY") != "" ? env("ARTIFACTORY_REPOSITORY") : "example-repo-local"
}

# ---------------------------------------------------------------------------
# ISO
# Note: Set using eval "$(./scripts/resolve-debian-iso.sh arm64|amd64)"
# ---------------------------------------------------------------------------

variable "iso_url" {
  type        = string
  description = "URL of the Debian .iso file to use for the build."
}

variable "iso_checksum" {
  type        = string
  description = "Checksum of the Debian .iso file to use for the build."
}

# ---------------------------------------------------------------------------
# Guest Identity
# ---------------------------------------------------------------------------

variable "build_username" {
  type        = string
  description = "Username to authenticate to the guest operating system."
  default     = "packer"
}

variable "build_password" {
  type        = string
  description = "Password to authenticate to the guest operating system."
  default     = "packer"
  sensitive   = true
}

variable "vm_guest_os_language" {
  type        = string
  description = "Language for the guest operating system."
  default     = "en"
}

variable "vm_guest_os_country" {
  type        = string
  description = "Country for the guest operating system."
  default     = "US"
}

variable "vm_guest_os_locale" {
  type        = string
  description = "Locale for the guest operating system."
  default     = "en_US.UTF-8"
}

variable "vm_guest_os_keyboard" {
  type        = string
  description = "Keyboard layout for the guest operating system."
  default     = "us"
}

variable "vm_guest_os_timezone" {
  type        = string
  description = "Timezone for the guest operating system."
  default     = "UTC"
}

variable "debian_mirror_hostname" {
  type        = string
  description = "Hostname of the Debian mirror to use for the build."
  default     = "deb.debian.org"
}

variable "ssh_timeout" {
  type        = string
  description = "Timeout for the SSH connection."
  default     = "30m"
}

variable "shutdown_command" {
  type        = string
  description = "Command to use to shut down the guest operating system."
  default     = null
}

# ---------------------------------------------------------------------------
# Sizing / Boot
# ---------------------------------------------------------------------------

variable "vm_name" {
  type        = string
  description = "Name of the virtual machine."
  default     = null
}

variable "cpus" {
  type        = number
  description = "Number of CPUs for the virtual machine."
  default     = 2
}

variable "memory" {
  type        = number
  description = "Memory for the virtual machine."
  default     = 2048
}

variable "disk_size" {
  type        = number
  description = "Disk size for the virtual machine."
  default     = 20480
}

variable "boot_wait" {
  type        = string
  description = "Time to wait for the virtual machine to boot."
  default     = "5s"
}

# ---------------------------------------------------------------------------
# Desktop (Defaults for VMware Fusion on Apple Silicon)
# ---------------------------------------------------------------------------

variable "guest_os_type" {
  type        = string
  description = "Guest operating system type for the virtual machine."
  default     = "arm-debian-64"
}

variable "network_adapter_type" {
  type        = string
  description = "Network adapter type for the virtual machine."
  default     = "e1000e"
}

variable "cdrom_adapter_type" {
  type        = string
  description = "CD-ROM adapter type for the virtual machine."
  default     = "sata"
}

variable "disk_adapter_type" {
  type        = string
  description = "Disk adapter type for the virtual machine."
  default     = "sata"
}

variable "format" {
  type        = string
  description = "Export format for desktop (vmware-iso) and vSphere (export.output_format): ova or ovf."
  default     = "ova"
  validation {
    condition     = contains(["ova", "ovf"], var.format)
    error_message = "Format must be \"ova\" or \"ovf\"."
  }
}

variable "ovftool_options" {
  type        = list(string)
  description = "Extra ovftool arguments for desktop (vmware-iso) export."
  default     = []
}

variable "vmx_data" {
  type        = map(string)
  description = "Extra VMX data for the virtual machine."
  default = {
    "usb_xhci.present" = "true"
  }
}

variable "boot_command" {
  type        = list(string)
  description = "Boot command for the virtual machine."
  default = [
    "<wait><up>e<wait>",
    "<down><down><down>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><wait>",
    "install <wait>",
    " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg <wait>",
    "debian-installer=en_US.UTF-8 <wait>auto <wait>locale=en_US.UTF-8 <wait>",
    "kbd-chooser/method=us <wait>keyboard-configuration/xkb-keymap=us <wait>",
    "netcfg/get_hostname={{ .Name }} <wait>netcfg/get_domain={{ .Name }} <wait>",
    "fb=false <wait>debconf/frontend=noninteractive <wait>",
    "console-setup/ask_detect=false <wait>console-keymaps-at/keymap=us <wait>",
    "grub-installer/bootdev=/dev/sda <wait>",
    "<f10><wait>"
  ]
}

# ---------------------------------------------------------------------------
# vSphere
# ---------------------------------------------------------------------------

variable "vsphere_server" {
  type        = string
  description = "Fully qualified domain name of the vCenter instance to use for the build."
  default     = env("VSPHERE_SERVER") != "" ? env("VSPHERE_SERVER") : "vc01.example.com"
}

variable "vsphere_username" {
  type        = string
  description = "Username to authenticate to the vSphere instance."
  default     = env("VSPHERE_USERNAME") != "" ? env("VSPHERE_USERNAME") : "[email protected]"
  sensitive   = true
}

variable "vsphere_password" {
  type        = string
  description = "Password to authenticate to the vSphere instance."
  default     = env("VSPHERE_PASSWORD") != "" ? env("VSPHERE_PASSWORD") : "VMw@re1!"
  sensitive   = true
}

variable "vsphere_datacenter" {
  type        = string
  description = "Datacenter in the vSphere inventory to use for the build."
  default     = env("VSPHERE_DATACENTER") != "" ? env("VSPHERE_DATACENTER") : "dc01"
}

variable "vsphere_cluster" {
  type        = string
  description = "Cluster in the vSphere inventory to use for the build."
  default     = env("VSPHERE_CLUSTER") != "" ? env("VSPHERE_CLUSTER") : "cl01"
}

variable "vsphere_datastore" {
  type        = string
  description = "Datastore in the vSphere inventory to use for the build."
  default     = env("VSPHERE_DATASTORE") != "" ? env("VSPHERE_DATASTORE") : "nfs"
}

variable "vsphere_network" {
  type        = string
  description = "Network in the vSphere inventory to use for the build."
  default     = env("VSPHERE_NETWORK") != "" ? env("VSPHERE_NETWORK") : "VM Network"
}

variable "vsphere_folder" {
  type        = string
  description = "Virtual machine folder in the vSphere inventory to use for the build."
  default     = env("VSPHERE_FOLDER") != "" ? env("VSPHERE_FOLDER") : "templates"
}

variable "vsphere_insecure" {
  type        = bool
  description = "Whether to use an insecure connection to the vSphere instance."
  default     = true
}

variable "vsphere_guest_os_type" {
  type        = string
  description = "Guest operating system type for the virtual machine."
  default     = "debian12_64Guest"
}

variable "vsphere_disk_controller_type" {
  type        = list(string)
  description = "Disk controller type for the virtual machine."
  default     = ["pvscsi"]
}

variable "vsphere_disk_thin_provisioned" {
  type        = bool
  description = "Whether to use thin provisioning for the virtual machine."
  default     = true
}

variable "vsphere_network_card" {
  type        = string
  description = "Network card type for the virtual machine."
  default     = "vmxnet3"
}

variable "vsphere_boot_command" {
  type        = list(string)
  description = "Boot command for the virtual machine."
  default = [
    "<wait><esc><wait>",
    "auto url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg ",
    "netcfg/get_hostname={{ .Name }}<enter>"
  ]
}

variable "vsphere_export_force" {
  type        = bool
  description = "Whether to force the export of the virtual machine."
  default     = true
}

variable "output_directory" {
  type        = string
  description = "Directory for build artifacts (desktop output and vSphere export)."
  default     = "output"
}

# ---------------------------------------------------------------------------
# Locals
# ---------------------------------------------------------------------------

locals {
  guest         = regex("debian-[0-9.]+-(?:amd64|arm64)", var.iso_url)
  artifact_name = coalesce(var.vm_name, local.guest)
  artifact_path = "${local.guest}/${formatdate("YYYYMMDDhhmmss", timestamp())}"
  shutdown_command = coalesce(
    var.shutdown_command,
    "echo '${var.build_password}' | sudo -S shutdown -P now"
  )

  data_source_content = {
    "/ks.cfg" = templatefile("${abspath(path.root)}/data/ks.pkrtpl.hcl", {
      build_username         = var.build_username
      build_password         = var.build_password
      vm_guest_os_language   = var.vm_guest_os_language
      vm_guest_os_country    = var.vm_guest_os_country
      vm_guest_os_locale     = var.vm_guest_os_locale
      vm_guest_os_keyboard   = var.vm_guest_os_keyboard
      vm_guest_os_timezone   = var.vm_guest_os_timezone
      debian_mirror_hostname = var.debian_mirror_hostname
    })
  }
}

Sources:

# VMware vSphere

source "vsphere-iso" "example" {
  vcenter_server      = var.vsphere_server
  username            = var.vsphere_username
  password            = var.vsphere_password
  insecure_connection = var.vsphere_insecure

  datacenter = var.vsphere_datacenter
  cluster    = var.vsphere_cluster
  datastore  = var.vsphere_datastore
  folder     = var.vsphere_folder

  vm_name       = local.artifact_name
  guest_os_type = var.vsphere_guest_os_type
  CPUs          = var.cpus
  RAM           = var.memory

  disk_controller_type = var.vsphere_disk_controller_type
  storage {
    disk_size             = var.disk_size
    disk_thin_provisioned = var.vsphere_disk_thin_provisioned
  }

  network_adapters {
    network_card = var.vsphere_network_card
    network      = var.vsphere_network
  }

  iso_url      = var.iso_url
  iso_checksum = var.iso_checksum

  ssh_username     = var.build_username
  ssh_password     = var.build_password
  ssh_timeout      = var.ssh_timeout
  shutdown_command = local.shutdown_command

  http_content = local.data_source_content
  boot_wait    = var.boot_wait
  boot_command = var.vsphere_boot_command

  export {
    force            = var.vsphere_export_force
    output_directory = var.output_directory
    output_format    = var.format
  }
}
# VMware Fusion / VMware Workstation

source "vmware-iso" "example" {
  iso_url              = var.iso_url
  iso_checksum         = var.iso_checksum
  vm_name              = local.artifact_name
  guest_os_type        = var.guest_os_type
  memory               = var.memory
  cpus                 = var.cpus
  disk_size            = var.disk_size
  ssh_username         = var.build_username
  ssh_password         = var.build_password
  ssh_timeout          = var.ssh_timeout
  shutdown_command     = local.shutdown_command
  output_directory     = var.output_directory
  format               = var.format
  ovftool_options      = var.ovftool_options
  network_adapter_type = var.network_adapter_type
  cdrom_adapter_type   = var.cdrom_adapter_type
  disk_adapter_type    = var.disk_adapter_type
  boot_wait            = var.boot_wait
  boot_command         = var.boot_command
  http_content         = local.data_source_content
  vmx_data             = var.vmx_data
}

Basic Authentication with Properties

build.pkr.hcl
# Basic Authentication with Custom Properties.

build {
  sources = [
    "source.vmware-iso.example",
    "source.vsphere-iso.example",
  ]

  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y open-vm-tools"
    ]
  }

  post-processor "artifactory" {
    url                      = var.artifactory_url
    username                 = var.artifactory_username
    password                 = var.artifactory_password
    repository               = var.artifactory_repository
    artifact_name            = local.artifact_name
    artifact_path            = local.artifact_path
    artifact_path_properties = true
    properties = {
      "version.number"  = "1.0.0"
      "build.number"    = "12345678"
      "release.channel" = "stable"
      "os.family"       = "linux"
      "os.vendor"       = "debian"
      "os.version"      = local.guest_version
      "os.arch"         = local.guest_arch
    }
  }
}
variables.pkr.hcl
# ---------------------------------------------------------------------------
# Artifactory Basic Authentication
# ---------------------------------------------------------------------------

variable "artifactory_url" {
  type        = string
  description = "URL of the Artifactory instance to use for the build."
  default     = env("ARTIFACTORY_URL") != "" ? env("ARTIFACTORY_URL") : "http://localhost:8081/artifactory"
}

variable "artifactory_username" {
  type        = string
  description = "Username to authenticate to the Artifactory instance."
  default     = env("ARTIFACTORY_USERNAME") != "" ? env("ARTIFACTORY_USERNAME") : "admin"
  sensitive   = true
}

variable "artifactory_password" {
  type        = string
  description = "Password to authenticate to the Artifactory instance."
  default     = env("ARTIFACTORY_PASSWORD") != "" ? env("ARTIFACTORY_PASSWORD") : "password"
  sensitive   = true
}

variable "artifactory_repository" {
  type        = string
  description = "Repository in the Artifactory instance to use for the build."
  default     = env("ARTIFACTORY_REPOSITORY") != "" ? env("ARTIFACTORY_REPOSITORY") : "example-repo-local"
}

# ---------------------------------------------------------------------------
# ISO
# Note: Set using eval "$(./scripts/resolve-debian-iso.sh arm64|amd64)"
# ---------------------------------------------------------------------------

variable "iso_url" {
  type        = string
  description = "URL of the Debian .iso file to use for the build."
}

variable "iso_checksum" {
  type        = string
  description = "Checksum of the Debian .iso file to use for the build."
}

# ---------------------------------------------------------------------------
# Guest Identity
# ---------------------------------------------------------------------------

variable "build_username" {
  type        = string
  description = "Username to authenticate to the guest operating system."
  default     = "packer"
}

variable "build_password" {
  type        = string
  description = "Password to authenticate to the guest operating system."
  default     = "packer"
  sensitive   = true
}

variable "vm_guest_os_language" {
  type        = string
  description = "Language for the guest operating system."
  default     = "en"
}

variable "vm_guest_os_country" {
  type        = string
  description = "Country for the guest operating system."
  default     = "US"
}

variable "vm_guest_os_locale" {
  type        = string
  description = "Locale for the guest operating system."
  default     = "en_US.UTF-8"
}

variable "vm_guest_os_keyboard" {
  type        = string
  description = "Keyboard layout for the guest operating system."
  default     = "us"
}

variable "vm_guest_os_timezone" {
  type        = string
  description = "Timezone for the guest operating system."
  default     = "UTC"
}

variable "debian_mirror_hostname" {
  type        = string
  description = "Hostname of the Debian mirror to use for the build."
  default     = "deb.debian.org"
}

variable "ssh_timeout" {
  type        = string
  description = "Timeout for the SSH connection."
  default     = "30m"
}

variable "shutdown_command" {
  type        = string
  description = "Command to use to shut down the guest operating system."
  default     = null
}

# ---------------------------------------------------------------------------
# Sizing / Boot
# ---------------------------------------------------------------------------

variable "vm_name" {
  type        = string
  description = "Name of the virtual machine."
  default     = null
}

variable "cpus" {
  type        = number
  description = "Number of CPUs for the virtual machine."
  default     = 2
}

variable "memory" {
  type        = number
  description = "Memory for the virtual machine."
  default     = 2048
}

variable "disk_size" {
  type        = number
  description = "Disk size for the virtual machine."
  default     = 20480
}

variable "boot_wait" {
  type        = string
  description = "Time to wait for the virtual machine to boot."
  default     = "5s"
}

# ---------------------------------------------------------------------------
# Desktop (Defaults for VMware Fusion on Apple Silicon)
# ---------------------------------------------------------------------------

variable "guest_os_type" {
  type        = string
  description = "Guest operating system type for the virtual machine."
  default     = "arm-debian-64"
}

variable "network_adapter_type" {
  type        = string
  description = "Network adapter type for the virtual machine."
  default     = "e1000e"
}

variable "cdrom_adapter_type" {
  type        = string
  description = "CD-ROM adapter type for the virtual machine."
  default     = "sata"
}

variable "disk_adapter_type" {
  type        = string
  description = "Disk adapter type for the virtual machine."
  default     = "sata"
}

variable "format" {
  type        = string
  description = "Export format for desktop (vmware-iso) and vSphere (export.output_format): ova or ovf."
  default     = "ova"
  validation {
    condition     = contains(["ova", "ovf"], var.format)
    error_message = "Format must be \"ova\" or \"ovf\"."
  }
}

variable "ovftool_options" {
  type        = list(string)
  description = "Extra ovftool arguments for desktop (vmware-iso) export."
  default     = []
}

variable "vmx_data" {
  type        = map(string)
  description = "Extra VMX data for the virtual machine."
  default = {
    "usb_xhci.present" = "true"
  }
}

variable "boot_command" {
  type        = list(string)
  description = "Boot command for the virtual machine."
  default = [
    "<wait><up>e<wait>",
    "<down><down><down>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><wait>",
    "install <wait>",
    " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg <wait>",
    "debian-installer=en_US.UTF-8 <wait>auto <wait>locale=en_US.UTF-8 <wait>",
    "kbd-chooser/method=us <wait>keyboard-configuration/xkb-keymap=us <wait>",
    "netcfg/get_hostname={{ .Name }} <wait>netcfg/get_domain={{ .Name }} <wait>",
    "fb=false <wait>debconf/frontend=noninteractive <wait>",
    "console-setup/ask_detect=false <wait>console-keymaps-at/keymap=us <wait>",
    "grub-installer/bootdev=/dev/sda <wait>",
    "<f10><wait>"
  ]
}

# ---------------------------------------------------------------------------
# vSphere
# ---------------------------------------------------------------------------

variable "vsphere_server" {
  type        = string
  description = "Fully qualified domain name of the vCenter instance to use for the build."
  default     = env("VSPHERE_SERVER") != "" ? env("VSPHERE_SERVER") : "vc01.example.com"
}

variable "vsphere_username" {
  type        = string
  description = "Username to authenticate to the vSphere instance."
  default     = env("VSPHERE_USERNAME") != "" ? env("VSPHERE_USERNAME") : "[email protected]"
  sensitive   = true
}

variable "vsphere_password" {
  type        = string
  description = "Password to authenticate to the vSphere instance."
  default     = env("VSPHERE_PASSWORD") != "" ? env("VSPHERE_PASSWORD") : "VMw@re1!"
  sensitive   = true
}

variable "vsphere_datacenter" {
  type        = string
  description = "Datacenter in the vSphere inventory to use for the build."
  default     = env("VSPHERE_DATACENTER") != "" ? env("VSPHERE_DATACENTER") : "dc01"
}

variable "vsphere_cluster" {
  type        = string
  description = "Cluster in the vSphere inventory to use for the build."
  default     = env("VSPHERE_CLUSTER") != "" ? env("VSPHERE_CLUSTER") : "cl01"
}

variable "vsphere_datastore" {
  type        = string
  description = "Datastore in the vSphere inventory to use for the build."
  default     = env("VSPHERE_DATASTORE") != "" ? env("VSPHERE_DATASTORE") : "nfs"
}

variable "vsphere_network" {
  type        = string
  description = "Network in the vSphere inventory to use for the build."
  default     = env("VSPHERE_NETWORK") != "" ? env("VSPHERE_NETWORK") : "VM Network"
}

variable "vsphere_folder" {
  type        = string
  description = "Virtual machine folder in the vSphere inventory to use for the build."
  default     = env("VSPHERE_FOLDER") != "" ? env("VSPHERE_FOLDER") : "templates"
}

variable "vsphere_insecure" {
  type        = bool
  description = "Whether to use an insecure connection to the vSphere instance."
  default     = true
}

variable "vsphere_guest_os_type" {
  type        = string
  description = "Guest operating system type for the virtual machine."
  default     = "debian12_64Guest"
}

variable "vsphere_disk_controller_type" {
  type        = list(string)
  description = "Disk controller type for the virtual machine."
  default     = ["pvscsi"]
}

variable "vsphere_disk_thin_provisioned" {
  type        = bool
  description = "Whether to use thin provisioning for the virtual machine."
  default     = true
}

variable "vsphere_network_card" {
  type        = string
  description = "Network card type for the virtual machine."
  default     = "vmxnet3"
}

variable "vsphere_boot_command" {
  type        = list(string)
  description = "Boot command for the virtual machine."
  default = [
    "<wait><esc><wait>",
    "auto url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg ",
    "netcfg/get_hostname={{ .Name }}<enter>"
  ]
}

variable "vsphere_export_force" {
  type        = bool
  description = "Whether to force the export of the virtual machine."
  default     = true
}

variable "output_directory" {
  type        = string
  description = "Directory for build artifacts (desktop output and vSphere export)."
  default     = "output"
}

# ---------------------------------------------------------------------------
# Locals
# ---------------------------------------------------------------------------

locals {
  # e.g. "debian-13.6.0-arm64" from the ISO URL
  guest         = regex("debian-[0-9.]+-(?:amd64|arm64)", var.iso_url)
  guest_version = regex("debian-([0-9.]+)-", local.guest)[0]
  guest_arch    = regex("-(amd64|arm64)$", local.guest)[0]

  artifact_name = coalesce(var.vm_name, local.guest)
  artifact_path = "${local.guest}/${formatdate("YYYYMMDDhhmmss", timestamp())}"
  shutdown_command = coalesce(
    var.shutdown_command,
    "echo '${var.build_password}' | sudo -S shutdown -P now"
  )

  data_source_content = {
    "/ks.cfg" = templatefile("${abspath(path.root)}/data/ks.pkrtpl.hcl", {
      build_username         = var.build_username
      build_password         = var.build_password
      vm_guest_os_language   = var.vm_guest_os_language
      vm_guest_os_country    = var.vm_guest_os_country
      vm_guest_os_locale     = var.vm_guest_os_locale
      vm_guest_os_keyboard   = var.vm_guest_os_keyboard
      vm_guest_os_timezone   = var.vm_guest_os_timezone
      debian_mirror_hostname = var.debian_mirror_hostname
    })
  }
}
sources-vmware-desktop.pkr.hcl
# VMware Fusion / VMware Workstation

source "vmware-iso" "example" {
  iso_url              = var.iso_url
  iso_checksum         = var.iso_checksum
  vm_name              = local.artifact_name
  guest_os_type        = var.guest_os_type
  memory               = var.memory
  cpus                 = var.cpus
  disk_size            = var.disk_size
  ssh_username         = var.build_username
  ssh_password         = var.build_password
  ssh_timeout          = var.ssh_timeout
  shutdown_command     = local.shutdown_command
  output_directory     = var.output_directory
  format               = var.format
  ovftool_options      = var.ovftool_options
  network_adapter_type = var.network_adapter_type
  cdrom_adapter_type   = var.cdrom_adapter_type
  disk_adapter_type    = var.disk_adapter_type
  boot_wait            = var.boot_wait
  boot_command         = var.boot_command
  http_content         = local.data_source_content
  vmx_data             = var.vmx_data
}
sources-vmware-vsphere.pkr.hcl
# VMware vSphere

source "vsphere-iso" "example" {
  vcenter_server      = var.vsphere_server
  username            = var.vsphere_username
  password            = var.vsphere_password
  insecure_connection = var.vsphere_insecure

  datacenter = var.vsphere_datacenter
  cluster    = var.vsphere_cluster
  datastore  = var.vsphere_datastore
  folder     = var.vsphere_folder

  vm_name       = local.artifact_name
  guest_os_type = var.vsphere_guest_os_type
  CPUs          = var.cpus
  RAM           = var.memory

  disk_controller_type = var.vsphere_disk_controller_type
  storage {
    disk_size             = var.disk_size
    disk_thin_provisioned = var.vsphere_disk_thin_provisioned
  }

  network_adapters {
    network_card = var.vsphere_network_card
    network      = var.vsphere_network
  }

  iso_url      = var.iso_url
  iso_checksum = var.iso_checksum

  ssh_username     = var.build_username
  ssh_password     = var.build_password
  ssh_timeout      = var.ssh_timeout
  shutdown_command = local.shutdown_command

  http_content = local.data_source_content
  boot_wait    = var.boot_wait
  boot_command = var.vsphere_boot_command

  export {
    force            = var.vsphere_export_force
    output_directory = var.output_directory
    output_format    = var.format
  }
}
versions.pkr.hcl
packer {
  required_plugins {
    artifactory = {
      version = ">= 0.1.0"
      source  = "github.com/tenthirtyam/artifactory"
    }
    vmware = {
      version = ">= 2.0.0"
      source  = "github.com/vmware/vmware"
    }
    vsphere = {
      version = ">= 2.0.0"
      source  = "github.com/vmware/vsphere"
    }
  }
}

API Key Authentication

build.pkr.hcl
# API Key Authentication.

build {
  sources = [
    "source.vmware-iso.example",
    "source.vsphere-iso.example",
  ]

  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y open-vm-tools"
    ]
  }

  post-processor "artifactory" {
    url             = var.artifactory_url
    api_key         = var.artifactory_api_key
    repository      = var.artifactory_repository
    artifact_name   = local.artifact_name
    artifact_path   = local.artifact_path
    overwrite       = true
    max_retries     = 5
    timeout_seconds = 60
  }
}
variables.pkr.hcl
# ---------------------------------------------------------------------------
# Artifactory API Key Authentication
# ---------------------------------------------------------------------------

variable "artifactory_url" {
  type        = string
  description = "URL of the Artifactory instance to use for the build."
  default     = env("ARTIFACTORY_URL") != "" ? env("ARTIFACTORY_URL") : "http://localhost:8081/artifactory"
}

variable "artifactory_api_key" {
  type        = string
  description = "API key to authenticate to the Artifactory instance."
  default     = env("ARTIFACTORY_API_KEY")
  sensitive   = true
}

variable "artifactory_repository" {
  type        = string
  description = "Repository in the Artifactory instance to use for the build."
  default     = env("ARTIFACTORY_REPOSITORY") != "" ? env("ARTIFACTORY_REPOSITORY") : "example-repo-local"
}

# ---------------------------------------------------------------------------
# ISO
# Note: Set using eval "$(./scripts/resolve-debian-iso.sh arm64|amd64)"
# ---------------------------------------------------------------------------

variable "iso_url" {
  type        = string
  description = "URL of the Debian .iso file to use for the build."
}

variable "iso_checksum" {
  type        = string
  description = "Checksum of the Debian .iso file to use for the build."
}

# ---------------------------------------------------------------------------
# Guest Identity (KS + SSH)
# ---------------------------------------------------------------------------

variable "build_username" {
  type        = string
  description = "Username to authenticate to the guest operating system."
  default     = "packer"
}

variable "build_password" {
  type        = string
  description = "Password to authenticate to the guest operating system."
  default     = "packer"
  sensitive   = true
}

variable "vm_guest_os_language" {
  type        = string
  description = "Language for the guest operating system."
  default     = "en"
}

variable "vm_guest_os_country" {
  type        = string
  description = "Country for the guest operating system."
  default     = "US"
}

variable "vm_guest_os_locale" {
  type        = string
  description = "Locale for the guest operating system."
  default     = "en_US.UTF-8"
}

variable "vm_guest_os_keyboard" {
  type        = string
  description = "Keyboard layout for the guest operating system."
  default     = "us"
}

variable "vm_guest_os_timezone" {
  type        = string
  description = "Timezone for the guest operating system."
  default     = "UTC"
}

variable "debian_mirror_hostname" {
  type        = string
  description = "Hostname of the Debian mirror to use for the build."
  default     = "deb.debian.org"
}

variable "ssh_timeout" {
  type        = string
  description = "Timeout for the SSH connection."
  default     = "30m"
}

variable "shutdown_command" {
  type        = string
  description = "Command to use to shut down the guest operating system."
  default     = null
}

# ---------------------------------------------------------------------------
# Shared VM Sizing / Boot
# ---------------------------------------------------------------------------

variable "vm_name" {
  type        = string
  description = "Name of the virtual machine."
  default     = null
}

variable "cpus" {
  type        = number
  description = "Number of CPUs for the virtual machine."
  default     = 2
}

variable "memory" {
  type        = number
  description = "Memory for the virtual machine."
  default     = 2048
}

variable "disk_size" {
  type        = number
  description = "Disk size for the virtual machine."
  default     = 20480
}

variable "boot_wait" {
  type        = string
  description = "Time to wait for the virtual machine to boot."
  default     = "5s"
}

# ---------------------------------------------------------------------------
# Desktop (Defaults for VMware Fusion on Apple Silicon)
# ---------------------------------------------------------------------------

variable "guest_os_type" {
  type        = string
  description = "Guest operating system type for the virtual machine."
  default     = "arm-debian-64"
}

variable "network_adapter_type" {
  type        = string
  description = "Network adapter type for the virtual machine."
  default     = "e1000e"
}

variable "cdrom_adapter_type" {
  type        = string
  description = "CD-ROM adapter type for the virtual machine."
  default     = "sata"
}

variable "disk_adapter_type" {
  type        = string
  description = "Disk adapter type for the virtual machine."
  default     = "sata"
}

variable "format" {
  type        = string
  description = "Export format for desktop (vmware-iso) and vSphere (export.output_format): ova or ovf."
  default     = "ova"
  validation {
    condition     = contains(["ova", "ovf"], var.format)
    error_message = "Format must be \"ova\" or \"ovf\"."
  }
}

variable "ovftool_options" {
  type        = list(string)
  description = "Extra ovftool arguments for desktop (vmware-iso) export."
  default     = []
}

variable "vmx_data" {
  type        = map(string)
  description = "Extra VMX data for the virtual machine."
  default = {
    "usb_xhci.present" = "true"
  }
}

variable "boot_command" {
  type        = list(string)
  description = "Boot command for the virtual machine."
  default = [
    "<wait><up>e<wait>",
    "<down><down><down>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><wait>",
    "install <wait>",
    " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg <wait>",
    "debian-installer=en_US.UTF-8 <wait>auto <wait>locale=en_US.UTF-8 <wait>",
    "kbd-chooser/method=us <wait>keyboard-configuration/xkb-keymap=us <wait>",
    "netcfg/get_hostname={{ .Name }} <wait>netcfg/get_domain={{ .Name }} <wait>",
    "fb=false <wait>debconf/frontend=noninteractive <wait>",
    "console-setup/ask_detect=false <wait>console-keymaps-at/keymap=us <wait>",
    "grub-installer/bootdev=/dev/sda <wait>",
    "<f10><wait>"
  ]
}

# ---------------------------------------------------------------------------
# vSphere
# ---------------------------------------------------------------------------

variable "vsphere_server" {
  type        = string
  description = "Fully qualified domain name of the vCenter instance to use for the build."
  default     = env("VSPHERE_SERVER") != "" ? env("VSPHERE_SERVER") : "vc01.example.com"
}

variable "vsphere_username" {
  type        = string
  description = "Username to authenticate to the vSphere instance."
  default     = env("VSPHERE_USERNAME") != "" ? env("VSPHERE_USERNAME") : "[email protected]"
  sensitive   = true
}

variable "vsphere_password" {
  type        = string
  description = "Password to authenticate to the vSphere instance."
  default     = env("VSPHERE_PASSWORD") != "" ? env("VSPHERE_PASSWORD") : "VMw@re1!"
  sensitive   = true
}

variable "vsphere_datacenter" {
  type        = string
  description = "Datacenter in the vSphere inventory to use for the build."
  default     = env("VSPHERE_DATACENTER") != "" ? env("VSPHERE_DATACENTER") : "dc01"
}

variable "vsphere_cluster" {
  type        = string
  description = "Cluster in the vSphere inventory to use for the build."
  default     = env("VSPHERE_CLUSTER") != "" ? env("VSPHERE_CLUSTER") : "cl01"
}

variable "vsphere_datastore" {
  type        = string
  description = "Datastore in the vSphere inventory to use for the build."
  default     = env("VSPHERE_DATASTORE") != "" ? env("VSPHERE_DATASTORE") : "nfs"
}

variable "vsphere_network" {
  type        = string
  description = "Network in the vSphere inventory to use for the build."
  default     = env("VSPHERE_NETWORK") != "" ? env("VSPHERE_NETWORK") : "VM Network"
}

variable "vsphere_folder" {
  type        = string
  description = "Virtual machine folder in the vSphere inventory to use for the build."
  default     = env("VSPHERE_FOLDER") != "" ? env("VSPHERE_FOLDER") : "templates"
}

variable "vsphere_insecure" {
  type        = bool
  description = "Whether to use an insecure connection to the vSphere instance."
  default     = true
}

variable "vsphere_guest_os_type" {
  type        = string
  description = "Guest operating system type for the virtual machine."
  default     = "debian12_64Guest"
}

variable "vsphere_disk_controller_type" {
  type        = list(string)
  description = "Disk controller type for the virtual machine."
  default     = ["pvscsi"]
}

variable "vsphere_disk_thin_provisioned" {
  type        = bool
  description = "Whether to use thin provisioning for the virtual machine."
  default     = true
}

variable "vsphere_network_card" {
  type        = string
  description = "Network card type for the virtual machine."
  default     = "vmxnet3"
}

variable "vsphere_boot_command" {
  type        = list(string)
  description = "Boot command for the virtual machine."
  default = [
    "<wait><esc><wait>",
    "auto url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg ",
    "netcfg/get_hostname={{ .Name }}<enter>"
  ]
}

variable "vsphere_export_force" {
  type        = bool
  description = "Whether to force the export of the virtual machine."
  default     = true
}

variable "output_directory" {
  type        = string
  description = "Directory for build artifacts (desktop output and vSphere export)."
  default     = "output"
}

# ---------------------------------------------------------------------------
# Locals
# ---------------------------------------------------------------------------

locals {
  guest         = regex("debian-[0-9.]+-(?:amd64|arm64)", var.iso_url)
  artifact_name = coalesce(var.vm_name, local.guest)
  artifact_path = "${local.guest}/${formatdate("YYYYMMDDhhmmss", timestamp())}"
  shutdown_command = coalesce(
    var.shutdown_command,
    "echo '${var.build_password}' | sudo -S shutdown -P now"
  )

  data_source_content = {
    "/ks.cfg" = templatefile("${abspath(path.root)}/data/ks.pkrtpl.hcl", {
      build_username         = var.build_username
      build_password         = var.build_password
      vm_guest_os_language   = var.vm_guest_os_language
      vm_guest_os_country    = var.vm_guest_os_country
      vm_guest_os_locale     = var.vm_guest_os_locale
      vm_guest_os_keyboard   = var.vm_guest_os_keyboard
      vm_guest_os_timezone   = var.vm_guest_os_timezone
      debian_mirror_hostname = var.debian_mirror_hostname
    })
  }
}
sources-vmware-desktop.pkr.hcl
# VMware Fusion / VMware Workstation

source "vmware-iso" "example" {
  iso_url              = var.iso_url
  iso_checksum         = var.iso_checksum
  vm_name              = local.artifact_name
  guest_os_type        = var.guest_os_type
  memory               = var.memory
  cpus                 = var.cpus
  disk_size            = var.disk_size
  ssh_username         = var.build_username
  ssh_password         = var.build_password
  ssh_timeout          = var.ssh_timeout
  shutdown_command     = local.shutdown_command
  output_directory     = var.output_directory
  format               = var.format
  ovftool_options      = var.ovftool_options
  network_adapter_type = var.network_adapter_type
  cdrom_adapter_type   = var.cdrom_adapter_type
  disk_adapter_type    = var.disk_adapter_type
  boot_wait            = var.boot_wait
  boot_command         = var.boot_command
  http_content         = local.data_source_content
  vmx_data             = var.vmx_data
}
sources-vmware-vsphere.pkr.hcl
# VMware vSphere

source "vsphere-iso" "example" {
  vcenter_server      = var.vsphere_server
  username            = var.vsphere_username
  password            = var.vsphere_password
  insecure_connection = var.vsphere_insecure

  datacenter = var.vsphere_datacenter
  cluster    = var.vsphere_cluster
  datastore  = var.vsphere_datastore
  folder     = var.vsphere_folder

  vm_name       = local.artifact_name
  guest_os_type = var.vsphere_guest_os_type
  CPUs          = var.cpus
  RAM           = var.memory

  disk_controller_type = var.vsphere_disk_controller_type
  storage {
    disk_size             = var.disk_size
    disk_thin_provisioned = var.vsphere_disk_thin_provisioned
  }

  network_adapters {
    network_card = var.vsphere_network_card
    network      = var.vsphere_network
  }

  iso_url      = var.iso_url
  iso_checksum = var.iso_checksum

  ssh_username     = var.build_username
  ssh_password     = var.build_password
  ssh_timeout      = var.ssh_timeout
  shutdown_command = local.shutdown_command

  http_content = local.data_source_content
  boot_wait    = var.boot_wait
  boot_command = var.vsphere_boot_command

  export {
    force            = var.vsphere_export_force
    output_directory = var.output_directory
    output_format    = var.format
  }
}
versions.pkr.hcl
packer {
  required_plugins {
    artifactory = {
      version = ">= 0.1.0"
      source  = "github.com/tenthirtyam/artifactory"
    }
    vmware = {
      version = ">= 2.0.0"
      source  = "github.com/vmware/vmware"
    }
    vsphere = {
      version = ">= 2.0.0"
      source  = "github.com/vmware/vsphere"
    }
  }
}

Access Token Authentication

build.pkr.hcl
# Access Token Authentication.

build {
  sources = [
    "source.vmware-iso.example",
    "source.vsphere-iso.example",
  ]

  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y open-vm-tools"
    ]
  }

  post-processor "artifactory" {
    url             = var.artifactory_url
    access_token    = var.artifactory_token
    repository      = var.artifactory_repository
    artifact_name   = local.artifact_name
    artifact_path   = local.artifact_path
    overwrite       = true
    max_retries     = 5
    timeout_seconds = 60
  }
}
`variables.pkr.hcl
# ---------------------------------------------------------------------------
# Artifactory Access Token Authentication
# ---------------------------------------------------------------------------

variable "artifactory_url" {
  type        = string
  description = "URL of the Artifactory instance to use for the build."
  default     = env("ARTIFACTORY_URL") != "" ? env("ARTIFACTORY_URL") : "http://localhost:8081/artifactory"
}

variable "artifactory_token" {
  type        = string
  description = "Access token to authenticate to the Artifactory instance."
  default     = env("ARTIFACTORY_TOKEN")
  sensitive   = true
}

variable "artifactory_repository" {
  type        = string
  description = "Repository in the Artifactory instance to use for the build."
  default     = env("ARTIFACTORY_REPOSITORY") != "" ? env("ARTIFACTORY_REPOSITORY") : "example-repo-local"
}

# ---------------------------------------------------------------------------
# ISO
# Note: Set using eval "$(./scripts/resolve-debian-iso.sh arm64|amd64)"
# ---------------------------------------------------------------------------

variable "iso_url" {
  type        = string
  description = "URL of the Debian .iso file to use for the build."
}

variable "iso_checksum" {
  type        = string
  description = "Checksum of the Debian .iso file to use for the build."
}

# ---------------------------------------------------------------------------
# Guest Identity
# ---------------------------------------------------------------------------

variable "build_username" {
  type        = string
  description = "Username to authenticate to the guest operating system."
  default     = "packer"
}

variable "build_password" {
  type        = string
  description = "Password to authenticate to the guest operating system."
  default     = "packer"
  sensitive   = true
}

variable "vm_guest_os_language" {
  type        = string
  description = "Language for the guest operating system."
  default     = "en"
}

variable "vm_guest_os_country" {
  type        = string
  description = "Country for the guest operating system."
  default     = "US"
}

variable "vm_guest_os_locale" {
  type        = string
  description = "Locale for the guest operating system."
  default     = "en_US.UTF-8"
}

variable "vm_guest_os_keyboard" {
  type        = string
  description = "Keyboard layout for the guest operating system."
  default     = "us"
}

variable "vm_guest_os_timezone" {
  type        = string
  description = "Timezone for the guest operating system."
  default     = "UTC"
}

variable "debian_mirror_hostname" {
  type        = string
  description = "Hostname of the Debian mirror to use for the build."
  default     = "deb.debian.org"
}

variable "ssh_timeout" {
  type        = string
  description = "Timeout for the SSH connection."
  default     = "30m"
}

variable "shutdown_command" {
  type        = string
  description = "Command to use to shut down the guest operating system."
  default     = null
}

# ---------------------------------------------------------------------------
# Sizing / Boot
# ---------------------------------------------------------------------------

variable "vm_name" {
  type        = string
  description = "Name of the virtual machine."
  default     = null
}

variable "cpus" {
  type        = number
  description = "Number of CPUs for the virtual machine."
  default     = 2
}

variable "memory" {
  type        = number
  description = "Memory for the virtual machine."
  default     = 2048
}

variable "disk_size" {
  type        = number
  description = "Disk size for the virtual machine."
  default     = 20480
}

variable "boot_wait" {
  type        = string
  description = "Time to wait for the virtual machine to boot."
  default     = "5s"
}

# ---------------------------------------------------------------------------
# Desktop (Defaults for VMware Fusion on Apple Silicon)
# ---------------------------------------------------------------------------

variable "guest_os_type" {
  type        = string
  description = "Guest operating system type for the virtual machine."
  default     = "arm-debian-64"
}

variable "network_adapter_type" {
  type        = string
  description = "Network adapter type for the virtual machine."
  default     = "e1000e"
}

variable "cdrom_adapter_type" {
  type        = string
  description = "CD-ROM adapter type for the virtual machine."
  default     = "sata"
}

variable "disk_adapter_type" {
  type        = string
  description = "Disk adapter type for the virtual machine."
  default     = "sata"
}

variable "format" {
  type        = string
  description = "Export format for desktop (vmware-iso) and vSphere (export.output_format): ova or ovf."
  default     = "ova"
  validation {
    condition     = contains(["ova", "ovf"], var.format)
    error_message = "Format must be \"ova\" or \"ovf\"."
  }
}

variable "ovftool_options" {
  type        = list(string)
  description = "Extra ovftool arguments for desktop (vmware-iso) export."
  default     = []
}

variable "vmx_data" {
  type        = map(string)
  description = "Extra VMX data for the virtual machine."
  default = {
    "usb_xhci.present" = "true"
  }
}

variable "boot_command" {
  type        = list(string)
  description = "Boot command for the virtual machine."
  default = [
    "<wait><up>e<wait>",
    "<down><down><down>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><right><right><right><right>",
    "<right><right><right><right><right><right><wait>",
    "install <wait>",
    " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg <wait>",
    "debian-installer=en_US.UTF-8 <wait>auto <wait>locale=en_US.UTF-8 <wait>",
    "kbd-chooser/method=us <wait>keyboard-configuration/xkb-keymap=us <wait>",
    "netcfg/get_hostname={{ .Name }} <wait>netcfg/get_domain={{ .Name }} <wait>",
    "fb=false <wait>debconf/frontend=noninteractive <wait>",
    "console-setup/ask_detect=false <wait>console-keymaps-at/keymap=us <wait>",
    "grub-installer/bootdev=/dev/sda <wait>",
    "<f10><wait>"
  ]
}

# ---------------------------------------------------------------------------
# vSphere
# ---------------------------------------------------------------------------

variable "vsphere_server" {
  type        = string
  description = "Fully qualified domain name of the vCenter instance to use for the build."
  default     = env("VSPHERE_SERVER") != "" ? env("VSPHERE_SERVER") : "vc01.example.com"
}

variable "vsphere_username" {
  type        = string
  description = "Username to authenticate to the vSphere instance."
  default     = env("VSPHERE_USERNAME") != "" ? env("VSPHERE_USERNAME") : "[email protected]"
  sensitive   = true
}

variable "vsphere_password" {
  type        = string
  description = "Password to authenticate to the vSphere instance."
  default     = env("VSPHERE_PASSWORD") != "" ? env("VSPHERE_PASSWORD") : "VMw@re1!"
  sensitive   = true
}

variable "vsphere_datacenter" {
  type        = string
  description = "Datacenter in the vSphere inventory to use for the build."
  default     = env("VSPHERE_DATACENTER") != "" ? env("VSPHERE_DATACENTER") : "dc01"
}

variable "vsphere_cluster" {
  type        = string
  description = "Cluster in the vSphere inventory to use for the build."
  default     = env("VSPHERE_CLUSTER") != "" ? env("VSPHERE_CLUSTER") : "cl01"
}

variable "vsphere_datastore" {
  type        = string
  description = "Datastore in the vSphere inventory to use for the build."
  default     = env("VSPHERE_DATASTORE") != "" ? env("VSPHERE_DATASTORE") : "nfs"
}

variable "vsphere_network" {
  type        = string
  description = "Network in the vSphere inventory to use for the build."
  default     = env("VSPHERE_NETWORK") != "" ? env("VSPHERE_NETWORK") : "VM Network"
}

variable "vsphere_folder" {
  type        = string
  description = "Virtual machine folder in the vSphere inventory to use for the build."
  default     = env("VSPHERE_FOLDER") != "" ? env("VSPHERE_FOLDER") : "templates"
}

variable "vsphere_insecure" {
  type        = bool
  description = "Whether to use an insecure connection to the vSphere instance."
  default     = true
}

variable "vsphere_guest_os_type" {
  type        = string
  description = "Guest operating system type for the virtual machine."
  default     = "debian12_64Guest"
}

variable "vsphere_disk_controller_type" {
  type        = list(string)
  description = "Disk controller type for the virtual machine."
  default     = ["pvscsi"]
}

variable "vsphere_disk_thin_provisioned" {
  type        = bool
  description = "Whether to use thin provisioning for the virtual machine."
  default     = true
}

variable "vsphere_network_card" {
  type        = string
  description = "Network card type for the virtual machine."
  default     = "vmxnet3"
}

variable "vsphere_boot_command" {
  type        = list(string)
  description = "Boot command for the virtual machine."
  default = [
    "<wait><esc><wait>",
    "auto url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg ",
    "netcfg/get_hostname={{ .Name }}<enter>"
  ]
}

variable "vsphere_export_force" {
  type        = bool
  description = "Whether to force the export of the virtual machine."
  default     = true
}

variable "output_directory" {
  type        = string
  description = "Directory for build artifacts (desktop output and vSphere export)."
  default     = "output"
}

# ---------------------------------------------------------------------------
# Locals
# ---------------------------------------------------------------------------

locals {
  guest         = regex("debian-[0-9.]+-(?:amd64|arm64)", var.iso_url)
  artifact_name = coalesce(var.vm_name, local.guest)
  artifact_path = "${local.guest}/${formatdate("YYYYMMDDhhmmss", timestamp())}"
  shutdown_command = coalesce(
    var.shutdown_command,
    "echo '${var.build_password}' | sudo -S shutdown -P now"
  )

  data_source_content = {
    "/ks.cfg" = templatefile("${abspath(path.root)}/data/ks.pkrtpl.hcl", {
      build_username         = var.build_username
      build_password         = var.build_password
      vm_guest_os_language   = var.vm_guest_os_language
      vm_guest_os_country    = var.vm_guest_os_country
      vm_guest_os_locale     = var.vm_guest_os_locale
      vm_guest_os_keyboard   = var.vm_guest_os_keyboard
      vm_guest_os_timezone   = var.vm_guest_os_timezone
      debian_mirror_hostname = var.debian_mirror_hostname
    })
  }
}
sources-vmware-desktop.pkr.hcl
# VMware Fusion / VMware Workstation

source "vmware-iso" "example" {
  iso_url              = var.iso_url
  iso_checksum         = var.iso_checksum
  vm_name              = local.artifact_name
  guest_os_type        = var.guest_os_type
  memory               = var.memory
  cpus                 = var.cpus
  disk_size            = var.disk_size
  ssh_username         = var.build_username
  ssh_password         = var.build_password
  ssh_timeout          = var.ssh_timeout
  shutdown_command     = local.shutdown_command
  output_directory     = var.output_directory
  format               = var.format
  ovftool_options      = var.ovftool_options
  network_adapter_type = var.network_adapter_type
  cdrom_adapter_type   = var.cdrom_adapter_type
  disk_adapter_type    = var.disk_adapter_type
  boot_wait            = var.boot_wait
  boot_command         = var.boot_command
  http_content         = local.data_source_content
  vmx_data             = var.vmx_data
}
sources-vmware-vsphere.pkr.hcl
# VMware vSphere

source "vsphere-iso" "example" {
  vcenter_server      = var.vsphere_server
  username            = var.vsphere_username
  password            = var.vsphere_password
  insecure_connection = var.vsphere_insecure

  datacenter = var.vsphere_datacenter
  cluster    = var.vsphere_cluster
  datastore  = var.vsphere_datastore
  folder     = var.vsphere_folder

  vm_name       = local.artifact_name
  guest_os_type = var.vsphere_guest_os_type
  CPUs          = var.cpus
  RAM           = var.memory

  disk_controller_type = var.vsphere_disk_controller_type
  storage {
    disk_size             = var.disk_size
    disk_thin_provisioned = var.vsphere_disk_thin_provisioned
  }

  network_adapters {
    network_card = var.vsphere_network_card
    network      = var.vsphere_network
  }

  iso_url      = var.iso_url
  iso_checksum = var.iso_checksum

  ssh_username     = var.build_username
  ssh_password     = var.build_password
  ssh_timeout      = var.ssh_timeout
  shutdown_command = local.shutdown_command

  http_content = local.data_source_content
  boot_wait    = var.boot_wait
  boot_command = var.vsphere_boot_command

  export {
    force            = var.vsphere_export_force
    output_directory = var.output_directory
    output_format    = var.format
  }
}
versions.pkr.hcl
packer {
  required_plugins {
    artifactory = {
      version = ">= 0.1.0"
      source  = "github.com/tenthirtyam/artifactory"
    }
    vmware = {
      version = ">= 2.0.0"
      source  = "github.com/vmware/vmware"
    }
    vsphere = {
      version = ">= 2.0.0"
      source  = "github.com/vmware/vsphere"
    }
  }
}

Note

Access token authentication is not supported on Artifactory open-source.