A production-ready Packer plugin for creating and provisioning virtual machines on VergeIO virtualization platform. This plugin provides complete VM lifecycle management with advanced features for enterprise environments.
Core VM Management:
- VM Creation: Complete VM creation with hardware, storage, and network configuration
- Intelligent Power Management: Real power state verification with configurable timeouts
- Disk Import Support: Automatic waiting for disk imports to complete before VM power-on
- Network Discovery: Dynamic network resolution by name using data sources
- Cloud-init Integration: Full cloud-init support with inline contents and external file loading
- Multi-platform: Supports Linux, Windows, and other operating systems
Advanced Capabilities:
- SSH/WinRM Connectivity: Optimized boot process leveraging Packer's communicator for reliability
- Static IP Configuration: Automatic extraction from cloud-init network configuration
- Graceful Shutdown: 4-phase shutdown process with power state verification
- Network Data Source: Query VergeIO networks by name for portable configurations
- Variable Management: Centralized credential management with sensitive value protection
- Error Recovery: Comprehensive rollback and cleanup on failures
Enterprise Ready:
- Production Tested: Used in live VergeIO environments
- Comprehensive Logging: Detailed debug output for troubleshooting
- API Integration: Full VergeIO API v4 support with proper error handling
- Builder (builder/vergeio) - Creates VMs with complete hardware configuration
- Network Data Source (datasource/vergeio) - Discovers network IDs by name
- Documentation (.web-docs) - Complete usage documentation
- Examples (example) - Working configuration examples
Add the following to your Packer configuration and run packer init:
packer {
required_plugins {
vergeio = {
source = "github.com/verge-io/vergeio"
version = ">=0.1.1"
}
}
}packer plugins install github.com/verge-io/vergeioCreate a variables file with your VergeIO credentials:
# Copy example variables
cp example/example.pkrvars.hcl example/local.pkrvars.hcl
# Edit with your VergeIO cluster details
vim example/local.pkrvars.hcl# Validate configuration
packer validate -var-file="example/local.pkrvars.hcl" example/build.pkr.hcl
# Build VM
packer build -var-file="example/local.pkrvars.hcl" example/build.pkr.hcl# Variables for VergeIO connection
variable "vergeio_endpoint" {
type = string
description = "VergeIO cluster endpoint"
}
variable "vergeio_username" {
type = string
description = "VergeIO cluster username"
}
variable "vergeio_password" {
type = string
description = "VergeIO cluster password"
sensitive = true
}
variable "static_ip_address" {
type = string
description = "Static IP address with CIDR notation"
default = "192.168.1.2/24"
}
variable "gateway_ip" {
type = string
description = "Gateway IP address"
default = "192.168.1.1"
}
# Network data source - discover network by name
data "vergeio-networks" "external_network" {
vergeio_endpoint = var.vergeio_endpoint
vergeio_username = var.vergeio_username
vergeio_password = var.vergeio_password
filter_name = "External" # Find network by name
}
# VergeIO VM source
source "vergeio" "example" {
# VergeIO connection
vergeio_endpoint = var.vergeio_endpoint
vergeio_username = var.vergeio_username
vergeio_password = var.vergeio_password
vergeio_insecure = true
vergeio_port = 443
# VM configuration
name = "packer-vm"
description = "VM built with Packer"
os_family = "linux"
cpu_cores = 4
ram = 4096
power_state = true
guest_agent = true
# Storage with import support
vm_disks {
name = "System Disk"
disksize = 20
interface = "virtio-scsi"
preferred_tier = 1
media = "import" # Automatic import waiting
media_source = 15 # Source disk/image ID
}
# Network with dynamic discovery
vm_nics {
name = "primary_nic"
vnet = data.vergeio-networks.external_network.networks[0].id
interface = "virtio"
assign_ipaddress = true
enabled = true
}
# Cloud-init configuration with inline contents
cloud_init_data_source = "nocloud"
cloud_init_files {
name = "user-data"
contents = <<-EOF
#cloud-config
users:
- name: packer
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
lock_passwd: false
passwd: $6$rounds=4096$salt$hash...
packages:
- curl
- wget
- htop
EOF
}
cloud_init_files {
name = "meta-data"
contents = <<-EOF
instance-id: packer-vm-${uuidv4()}
local-hostname: packer-vm
EOF
}
# SSH connectivity
communicator = "ssh"
ssh_username = "packer"
ssh_password = "your-password"
ssh_timeout = "20m"
# Power-on timeout configuration (optional)
# power_on_timeout = "3m" # How long to wait for VM to power on (default: 2m)
# boot_timeout = "7m" # Kept for compatibility (not used - SSH communicator handles boot waiting)
# Graceful shutdown
shutdown_command = "sudo shutdown -P now"
shutdown_timeout = "5m"
}
# Build with provisioning
build {
sources = ["source.vergeio.example"]
# Verify SSH connectivity and system state
provisioner "shell" {
inline = [
"echo 'SSH connection successful!'",
"whoami",
"hostname",
"ip addr show",
"echo 'VM provisioning completed!'"
]
}
}The plugin automatically handles disk imports with media="import":
vm_disks {
media = "import"
media_source = 15 # Source disk/image ID
}The plugin will:
- Create the disk with import configuration
- Wait for import to complete (prevents power-on errors)
- Proceed with VM power-on only after import success
Discover networks dynamically instead of hardcoding IDs:
data "vergeio-networks" "external" {
filter_name = "External" # Network name
}
vm_nics {
vnet = data.vergeio-networks.external.networks[0].id
}The plugin supports both inline contents and external file loading for cloud-init configuration:
cloud_init_files {
name = "user-data"
contents = <<-EOF
#cloud-config
hostname: my-vm
users:
- name: admin
sudo: ALL=(ALL) NOPASSWD:ALL
EOF
}# Single file
cloud_init_files {
name = "user-data"
files = ["cloud-init/user-data.yml"]
}
# Multiple files (concatenated)
cloud_init_files {
name = "user-data"
files = [
"cloud-init/base-config.yml",
"cloud-init/packages.yml",
"cloud-init/services.yml"
]
}- Mutually Exclusive: Use either
contentsORfiles, never both - Optional: Both
contentsandfilesare optional - entries without either are skipped - Multiple Files: Files are concatenated with newlines in the order specified
- Path Resolution: Relative paths are resolved from the Packer template directory
- Validation: Files must exist and be readable during configuration validation
project/
├── build.pkr.hcl
├── cloud-init/
│ ├── user-data.yml # Base user configuration
│ ├── meta-data.yml # Instance metadata
│ ├── network-config.yml # Network configuration
│ ├── packages.yml # Additional packages
│ └── services.yml # Service configuration
└── variables.pkrvars.hcl
cloud_init_data_source = "nocloud"
# Load base configuration from file
cloud_init_files {
name = "user-data"
files = ["cloud-init/user-data.yml"]
}
# Load metadata from file
cloud_init_files {
name = "meta-data"
files = ["cloud-init/meta-data.yml"]
}
# Combine multiple configuration files
cloud_init_files {
name = "user-data-extended"
files = [
"cloud-init/base-config.yml",
"cloud-init/packages.yml",
"cloud-init/services.yml"
]
}
# Optional cloud-init file (skipped if no contents/files)
cloud_init_files {
name = "vendor-data"
# No contents or files - this entry will be skipped
}Centralized credential management:
# Define once
variable "vergeio_password" {
type = string
sensitive = true
}
# Use everywhere
data "vergeio-networks" "net" {
vergeio_password = var.vergeio_password
}
source "vergeio" "vm" {
vergeio_password = var.vergeio_password
}The plugin executes builds in these phases:
- VM Creation: VM + Disks + NICs creation
- Disk Import Completion: Wait for any import disks to finish
- Power Management: VM power-on with status verification
- Network Discovery: IP address discovery (guest agent)
- Provisioning: SSH/WinRM connectivity and provisioning
- Cleanup: Graceful shutdown and finalization
Tested Operating Systems:
- Linux distributions (Ubuntu, CentOS, Debian)
- Windows Server (with WinRM)
Communication Methods:
- SSH (Linux)
- WinRM (Windows)
- Custom communicators
Enable Debug Logging:
PACKER_LOG=1 packer build -var-file="local.pkrvars.hcl" build.pkr.hclCommon Issues:
- "No such file or directory" for vnet: Network ID doesn't exist - use network data source
- "Cannot power on VM while drives importing": Fixed automatically with import waiting
- SSH timeout: Check cloud-init configuration and network settings
- Guest agent not reporting IP: Ensure guest agent is installed on source image
# Clone repository
git clone https://github.com/verge-io/packer-plugin-vergeio.git
cd packer-plugin-vergeio
# Build plugin
go build -ldflags="-X github.com/verge-io/packer-plugin-vergeio/version.VersionPrerelease=dev" -o packer-plugin-vergeio
# Install locally
packer plugins install --path packer-plugin-vergeio github.com/verge-io/vergeio# Install plugin locally first
make dev
# Run acceptance tests
PACKER_ACC=1 go test -count 1 -v ./... -timeout=120m# Quick development build and install
make dev$MODULE_NAME = (Get-Content go.mod | Where-Object { $_ -match "^module" }) -replace 'module ',''
$FQN = $MODULE_NAME -replace 'packer-plugin-',''
go build -ldflags="-X $MODULE_NAME/version.VersionPrerelease=dev" -o packer-plugin-vergeio.exe
packer plugins install --path packer-plugin-vergeio.exe $FQN- Go: >= 1.20
- Packer: >= v1.10.2
- packer-plugin-sdk: >= v0.6.1
- VergeIO: API v4 compatible cluster
This project is licensed under the Mozilla Public License 2.0 - see the LICENSE file for details.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
For issues and questions:
- GitHub Issues: packer-plugin-vergeio/issues
- VergeIO Documentation: VergeIO Docs
- Packer Documentation: Packer Docs