Last active
March 15, 2024 15:24
-
-
Save bvierra/55f1aa4ac225aa83176e8c424165ae1f to your computer and use it in GitHub Desktop.
proxmox qemu vm module w/cloud-init
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# use Telmate/proxmox 3.0.1-rc1 provider | |
terraform { | |
required_providers { | |
proxmox = { | |
source = "Telmate/proxmox" | |
version = "3.0.1-rc1" | |
} | |
} | |
} | |
# Load the file from var.vm_ssh_private_key_path and var.vm_ssh_public_key_path as local sensitive files to keep the contents from being displayed in the plan output | |
data "local_sensitive_file" "ssh_private_key" { | |
filename = var.vm_ssh_private_key_path | |
} | |
data "local_sensitive_file" "ssh_public_key" { | |
filename = var.vm_ssh_public_key_path | |
} | |
# Create the cloud-init file from template and store into the generated folder | |
resource "local_sensitive_file" "cloud_init" { | |
content = templatefile(local.template_ci_userdata_filename, { | |
hostname = var.vm_name, | |
fqdn = "${var.vm_name}.${var.vm_domain_name}", | |
ansible_user = var.ansible_user, | |
ansible_password = var.ansible_password, | |
ansible_public_key = data.local_sensitive_file.ssh_public_key.content, | |
serial_added = local.serial_added | |
}) | |
filename = "${var.generated_folder}/cloud-init/${var.project_name}-${var.vm_name}-cloud_init.yml" | |
file_permission = "0644" | |
} | |
# Transfer the cloud-init file from the generated folder to the Proxmox server | |
# This only triggers if the sha1 from the cloud_init creation changes | |
resource "null_resource" "cloud_init" { | |
connection { | |
type = "ssh" | |
user = var.vm_proxmox_ssh_user | |
private_key = file(var.vm_proxmox_ssh_private_key_path) | |
host = var.vm_proxmox_ssh_server | |
} | |
provisioner "file" { | |
source = local_sensitive_file.cloud_init.filename | |
destination = "/mnt/pve/${var.vm_proxmox_snippets_storage_pool}/snippets/${var.project_name}-${var.vm_name}-cloud_init.yml" | |
} | |
triggers = { | |
cloud_init_sh1 = resource.local_sensitive_file.cloud_init.content_sha1 | |
} | |
} | |
resource "proxmox_vm_qemu" "vm" { | |
depends_on = [ | |
null_resource.cloud_init | |
] | |
name = var.vm_name | |
target_node = var.vm_target_node | |
clone = var.vm_clone | |
full_clone = var.vm_full_clone | |
hastate = var.vm_hastate | |
hagroup = var.vm_hagroup | |
agent = var.vm_agent | |
desc = var.vm_description | |
qemu_os = var.vm_qemu_os | |
balloon = var.vm_memory_minimum | |
memory = var.vm_memory_maximum | |
numa = var.vm_numa | |
sockets = var.vm_sockets | |
cores = var.vm_cores | |
cpu = var.vm_cpu | |
hotplug = var.vm_hotplug | |
scsihw = var.vm_scsi_controller | |
pool = var.vm_pool | |
disks { | |
virtio { | |
virtio0 { | |
disk { | |
storage = var.vm_disk_storage | |
size = var.vm_disk_size | |
format = var.vm_disk_format | |
iothread = var.vm_scsi_controller == "virtio-scsi-single" ? true : false | |
cache = var.vm_disk_cache | |
} | |
} | |
} | |
} | |
serial { | |
id = var.vm_serial_id | |
type = var.vm_serial_type | |
} | |
os_type = "cloud-init" | |
nameserver = var.vm_nameserver | |
cicustom = "user=${var.vm_proxmox_snippets_storage_pool}:snippets/${var.project_name}-${var.vm_name}-cloud_init.yml" | |
cloudinit_cdrom_storage = var.vm_cloudinit_cdrom_storage | |
ipconfig0 = length(var.vm_ipconfig) >= 1 ? var.vm_ipconfig[0] : null | |
ipconfig1 = length(var.vm_ipconfig) >= 2 ? var.vm_ipconfig[1] : null | |
ipconfig2 = length(var.vm_ipconfig) >= 3 ? var.vm_ipconfig[2] : null | |
ipconfig3 = length(var.vm_ipconfig) >= 4 ? var.vm_ipconfig[3] : null | |
ipconfig4 = length(var.vm_ipconfig) >= 5 ? var.vm_ipconfig[4] : null | |
ipconfig5 = length(var.vm_ipconfig) >= 6 ? var.vm_ipconfig[5] : null | |
ipconfig6 = length(var.vm_ipconfig) >= 7 ? var.vm_ipconfig[6] : null | |
ipconfig7 = length(var.vm_ipconfig) >= 8 ? var.vm_ipconfig[7] : null | |
ipconfig8 = length(var.vm_ipconfig) >= 9 ? var.vm_ipconfig[8] : null | |
dynamic "network" { | |
for_each = var.vm_networks | |
iterator = network | |
content { | |
model = network.value["model"] | |
bridge = network.value["bridge"] | |
tag = network.value["tag"] | |
firewall = network.value["firewall"] | |
link_down = network.value["link_down"] | |
} | |
} | |
force_recreate_on_change_of = resource.local_sensitive_file.cloud_init.content_sha1 | |
tags = var.vm_tags | |
} | |
output "ssh_host" { | |
value = proxmox_vm_qemu.vm.ssh_host | |
} | |
output "name" { | |
value = proxmox_vm_qemu.vm.name | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#cloud-config | |
preserve_hostname: false | |
hostname: ${hostname} | |
fqdn: ${fqdn} | |
prefer_fqdn_over_hostname: true | |
manage_etc_hosts: true | |
package_update: true | |
package_upgrade: true | |
packages: | |
- vim | |
- tmux | |
- git | |
- curl | |
- wget | |
- sudo | |
- ansible | |
%{ if serial_added ~} | |
runcmd: | |
- [ systemctl, enable, [email protected] ] | |
- [ systemctl, start, --no-block, [email protected] ] | |
%{ endif ~} | |
users: | |
- name: ${ansible_user} | |
passwd: ${ansible_password} | |
ssh-authorized-keys: | |
- ${ansible_public_key} | |
sudo: ['ALL=(ALL) NOPASSWD:ALL'] | |
groups: sudo, admin | |
shell: /bin/bash | |
power_state: | |
mode: reboot | |
message: Restarting after setup |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
variable "project_name" { | |
description = "The name of the project" | |
type = string | |
} | |
variable "vm_name" { | |
description = "The name of the VM" | |
type = string | |
} | |
variable "vm_target_node" { | |
description = "The name of the Proxmox node to create the VM on" | |
type = string | |
} | |
variable "vm_clone" { | |
description = "The name of the template to clone" | |
type = string | |
} | |
variable "vm_full_clone" { | |
description = "Whether to do a full clone or not" | |
type = bool | |
default = true | |
} | |
variable "vm_hastate" { | |
description = "The HA state of the VM" | |
type = string | |
default = null | |
} | |
variable "vm_hagroup" { | |
description = "The HA group of the VM" | |
type = string | |
default = null | |
} | |
variable "vm_agent" { | |
description = "If qemu-guest agent is running on the VM" | |
type = number | |
default = 1 | |
} | |
variable "vm_description" { | |
description = "The description to set for the VM" | |
type = string | |
default = " " | |
} | |
variable "vm_qemu_os" { | |
description = "The OS of the VM" | |
type = string | |
default = "l26" | |
} | |
variable "vm_memory_minimum" { | |
description = "The minimum amount of memory to allocate to the VM (in MB). If set to 0 then ballooning is disabled" | |
type = number | |
default = 512 | |
} | |
variable "vm_memory_maximum" { | |
description = "The maximum amount of memory to allocate to the VM (in MB). If vm_memory_minimum is set to 0 (ballooning disabled) then this is the static amount" | |
type = number | |
default = 1024 | |
} | |
variable "vm_numa" { | |
description = "Enable NUMA on the VM (if enabled vm_cores should be set to the number of nodes in the NUMA topology)" | |
type = bool | |
default = false | |
} | |
variable "vm_sockets" { | |
description = "The number of sockets to allocate to the VM" | |
type = number | |
default = 1 | |
} | |
variable "vm_cores" { | |
description = "The number of cores to allocate to the VM" | |
type = number | |
default = 1 | |
} | |
variable "vm_cpu" { | |
description = "The CPU type to allocate to the VM" | |
type = string | |
default = "host" | |
} | |
variable "vm_hotplug" { | |
description = "Hotplug features to enable on the VM. Valid values are network,disk,usb,cpu,memory (cpu,memory both require vm_numa to be set to true)" | |
type = string | |
default = "network,disk,usb" | |
} | |
variable "vm_scsi_controller" { | |
description = "The SCSI controller model to emulate. Can be lsi, lsi53c810, virtio-scsi-pci, virtio-scsi-single, megasas, or pvscsi." | |
type = string | |
default = "lsi" | |
} | |
variable "vm_pool" { | |
description = "The storage pool to create the VM in" | |
type = string | |
default = null | |
} | |
variable "vm_os_type" { | |
description = "The OS type of the VM" | |
type = string | |
default = "ubuntu" | |
} | |
variable "vm_disk_type" { | |
description = "The disk type of the hdd in the VM. Options: ide, sata, scsi, virtio." | |
type = string | |
default = "scsi" | |
} | |
variable "vm_disk_storage" { | |
description = "The storage pool to ciscsireate the VM disk in" | |
type = string | |
default = "local" | |
} | |
variable "vm_disk_size" { | |
description = "The size of the VM disk" | |
type = number | |
default = "20" | |
} | |
variable "vm_disk_format" { | |
description = "The format of the VM disk" | |
type = string | |
default = "raw" | |
} | |
variable "vm_disk_ssd" { | |
description = "Whether the VM disk is an SSD or not" | |
type = number | |
default = 0 | |
} | |
variable "vm_disk_iothread" { | |
description = "Create one I/O thread per storage controller, rather than a single thread for all I/O. Requires vm_scsi_controller = virtio-scsi-single and a vm_disk_type = scsi or virtio." | |
type = number | |
default = 1 | |
} | |
variable "vm_disk_cache" { | |
description = "The cache mode of the VM disk. Options: directsync, none, unsafe, writeback, writethrough" | |
type = string | |
default = "none" | |
} | |
variable "vm_networks" { | |
description = "The network configuration for the VM" | |
type = list(object({ | |
bridge = string | |
firewall = bool | |
link_down = bool | |
model = string | |
tag = number | |
})) | |
default = [ | |
{ | |
bridge = "vmbr0" | |
firewall = false | |
link_down = false | |
model = "virtio" | |
tag = -1 | |
} | |
] | |
} | |
variable "vm_serial_id" { | |
description = "The ID of the serial device for the VM. Must be unique, and between 0-3 or null to not create a serial device" | |
type = number | |
default = null | |
} | |
variable "vm_serial_type" { | |
description = "The type of the serial device for the VM. Can be socket or a dev on the host (e.g. /dev/ttyS0), if you do this you cannot migrate the VM" | |
type = string | |
default = null | |
} | |
variable "vm_cloudinit_cdrom_storage" { | |
description = "The storage pool to create the cloud-init cdrom in" | |
type = string | |
default = "local" | |
} | |
variable "vm_ssh_user" { | |
description = "The SSH user to use to connect to the VM" | |
type = string | |
default = "root" | |
} | |
variable "vm_ssh_private_key_path" { | |
description = "The path the the ssh private key to connect to the VM with" | |
type = string | |
default = null | |
} | |
variable "vm_ssh_public_key_path" { | |
description = "The path the the ssh public key to connect to provision with" | |
type = string | |
default = null | |
} | |
variable "vm_domain_name" { | |
description = "The domain for the VM" | |
type = string | |
default = "localdomain" | |
} | |
variable "vm_ipconfig" { | |
description = "The static IP configuration for the VM, should be 'ip=dhcp' if using DHCP. Format: ip=10.10.120.254/24,gw=10.10.120.1" | |
type = list(string) | |
default = ["ip=dhcp"] | |
} | |
variable "vm_nameserver" { | |
description = "The nameserver to use for the VM (only required if not using dhcp)" | |
type = string | |
default = null | |
} | |
variable "vm_proxmox_ssh_server" { | |
description = "The IP/Hostname of the server to upload cloud-init files to" | |
type = string | |
} | |
variable "vm_proxmox_ssh_user" { | |
description = "The SSH user to use to connect to the Proxmox server with. This is used to upload the cloud-init file. This user must have write access to the snippets directory on the datastore used" | |
type = string | |
default = "root" | |
} | |
variable "vm_proxmox_ssh_private_key_path" { | |
description = "The path the the ssh private key to connect to the Proxmox server with" | |
type = string | |
} | |
variable "vm_proxmox_snippets_storage_pool" { | |
description = "The storage pool to create the cloud-init snippets in" | |
type = string | |
default = "local" | |
} | |
variable "ansible_user" { | |
description = "The user to use for Ansible" | |
type = string | |
default = "ansible" | |
} | |
variable "ansible_password" { | |
description = "The hashed password to use for Ansible" | |
type = string | |
default = null | |
} | |
variable "ansible_public_key" { | |
description = "value of the public key to use for Ansible" | |
type = string | |
default = null | |
} | |
variable "vm_tags" { | |
description = "The tags to apply to the VM" | |
type = string | |
default = null | |
} | |
variable "templates_folder" { | |
description = "The location of the templates folder (default should be fine)" | |
type = string | |
default = "./shared/templates" | |
} | |
variable "generated_folder" { | |
description = "The location of the folder that will hold generated files" | |
type = string | |
default = "./generated" | |
} | |
locals { | |
template_ci_userdata_filename = "${var.templates_folder}/cloud-init/user-data.tftpl" | |
serial_added = var.vm_serial_id >= 0 ? true : false | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment